From 3e3fe1608802dd4b3eacb6230fc13a7cff48ae96 Mon Sep 17 00:00:00 2001 From: Maciek Baron Date: Sat, 27 Jun 2020 19:09:26 +0100 Subject: [PATCH 01/74] Add Pokemon Red constants --- .../game_wrapper_pokemon_red/constants.py | 1399 +++++++++++++++++ 1 file changed, 1399 insertions(+) create mode 100644 pyboy/plugins/game_wrapper_pokemon_red/constants.py diff --git a/pyboy/plugins/game_wrapper_pokemon_red/constants.py b/pyboy/plugins/game_wrapper_pokemon_red/constants.py new file mode 100644 index 000000000..4e857a32f --- /dev/null +++ b/pyboy/plugins/game_wrapper_pokemon_red/constants.py @@ -0,0 +1,1399 @@ +STRING_TERMINATOR = 80 +ASCII_DELTA = 63 + +# Moves +MOVE_POUND = 0x01 +MOVE_KARATE_CHOP = 0x02 +MOVE_DOUBLESLAP = 0x03 +MOVE_COMET_PUNCH = 0x04 +MOVE_MEGA_PUNCH = 0x05 +MOVE_PAY_DAY = 0x06 +MOVE_FIRE_PUNCH = 0x07 +MOVE_ICE_PUNCH = 0x08 +MOVE_THUNDERPUNCH = 0x09 +MOVE_SCRATCH = 0x0a +MOVE_VICEGRIP = 0x0b +MOVE_GUILLOTINE = 0x0c +MOVE_RAZOR_WIND = 0x0d +MOVE_SWORDS_DANCE = 0x0e +MOVE_CUT = 0x0f +MOVE_GUST = 0x10 +MOVE_WING_ATTACK = 0x11 +MOVE_WHIRLWIND = 0x12 +MOVE_FLY = 0x13 +MOVE_BIND = 0x14 +MOVE_SLAM = 0x15 +MOVE_VINE_WHIP = 0x16 +MOVE_STOMP = 0x17 +MOVE_DOUBLE_KICK = 0x18 +MOVE_MEGA_KICK = 0x19 +MOVE_JUMP_KICK = 0x1a +MOVE_ROLLING_KICK = 0x1b +MOVE_SAND_ATTACK = 0x1c +MOVE_HEADBUTT = 0x1d +MOVE_HORN_ATTACK = 0x1e +MOVE_FURY_ATTACK = 0x1f +MOVE_HORN_DRILL = 0x20 +MOVE_TACKLE = 0x21 +MOVE_BODY_SLAM = 0x22 +MOVE_WRAP = 0x23 +MOVE_TAKE_DOWN = 0x24 +MOVE_THRASH = 0x25 +MOVE_DOUBLE_EDGE = 0x26 +MOVE_TAIL_WHIP = 0x27 +MOVE_POISON_STING = 0x28 +MOVE_TWINEEDLE = 0x29 +MOVE_PIN_MISSILE = 0x2a +MOVE_LEER = 0x2b +MOVE_BITE = 0x2c +MOVE_GROWL = 0x2d +MOVE_ROAR = 0x2e +MOVE_SING = 0x2f +MOVE_SUPERSONIC = 0x30 +MOVE_SONICBOOM = 0x31 +MOVE_DISABLE = 0x32 +MOVE_ACID = 0x33 +MOVE_EMBER = 0x34 +MOVE_FLAMETHROWER = 0x35 +MOVE_MIST = 0x36 +MOVE_WATER_GUN = 0x37 +MOVE_HYDRO_PUMP = 0x38 +MOVE_SURF = 0x39 +MOVE_ICE_BEAM = 0x3a +MOVE_BLIZZARD = 0x3b +MOVE_PSYBEAM = 0x3c +MOVE_BUBBLEBEAM = 0x3d +MOVE_AURORA_BEAM = 0x3e +MOVE_HYPER_BEAM = 0x3f +MOVE_PECK = 0x40 +MOVE_DRILL_PECK = 0x41 +MOVE_SUBMISSION = 0x42 +MOVE_LOW_KICK = 0x43 +MOVE_COUNTER = 0x44 +MOVE_SEISMIC_TOSS = 0x45 +MOVE_STRENGTH = 0x46 +MOVE_ABSORB = 0x47 +MOVE_MEGA_DRAIN = 0x48 +MOVE_LEECH_SEED = 0x49 +MOVE_GROWTH = 0x4a +MOVE_RAZOR_LEAF = 0x4b +MOVE_SOLARBEAM = 0x4c +MOVE_POISONPOWDER = 0x4d +MOVE_STUN_SPORE = 0x4e +MOVE_SLEEP_POWDER = 0x4f +MOVE_PETAL_DANCE = 0x50 +MOVE_STRING_SHOT = 0x51 +MOVE_DRAGON_RAGE = 0x52 +MOVE_FIRE_SPIN = 0x53 +MOVE_THUNDERSHOCK = 0x54 +MOVE_THUNDERBOLT = 0x55 +MOVE_THUNDER_WAVE = 0x56 +MOVE_THUNDER = 0x57 +MOVE_ROCK_THROW = 0x58 +MOVE_EARTHQUAKE = 0x59 +MOVE_FISSURE = 0x5a +MOVE_DIG = 0x5b +MOVE_TOXIC = 0x5c +MOVE_CONFUSION = 0x5d +MOVE_PSYCHIC_M = 0x5e +MOVE_HYPNOSIS = 0x5f +MOVE_MEDITATE = 0x60 +MOVE_AGILITY = 0x61 +MOVE_QUICK_ATTACK = 0x62 +MOVE_RAGE = 0x63 +MOVE_TELEPORT = 0x64 +MOVE_NIGHT_SHADE = 0x65 +MOVE_MIMIC = 0x66 +MOVE_SCREECH = 0x67 +MOVE_DOUBLE_TEAM = 0x68 +MOVE_RECOVER = 0x69 +MOVE_HARDEN = 0x6a +MOVE_MINIMIZE = 0x6b +MOVE_SMOKESCREEN = 0x6c +MOVE_CONFUSE_RAY = 0x6d +MOVE_WITHDRAW = 0x6e +MOVE_DEFENSE_CURL = 0x6f +MOVE_BARRIER = 0x70 +MOVE_LIGHT_SCREEN = 0x71 +MOVE_HAZE = 0x72 +MOVE_REFLECT = 0x73 +MOVE_FOCUS_ENERGY = 0x74 +MOVE_BIDE = 0x75 +MOVE_METRONOME = 0x76 +MOVE_MIRROR_MOVE = 0x77 +MOVE_SELFDESTRUCT = 0x78 +MOVE_EGG_BOMB = 0x79 +MOVE_LICK = 0x7a +MOVE_SMOG = 0x7b +MOVE_SLUDGE = 0x7c +MOVE_BONE_CLUB = 0x7d +MOVE_FIRE_BLAST = 0x7e +MOVE_WATERFALL = 0x7f +MOVE_CLAMP = 0x80 +MOVE_SWIFT = 0x81 +MOVE_SKULL_BASH = 0x82 +MOVE_SPIKE_CANNON = 0x83 +MOVE_CONSTRICT = 0x84 +MOVE_AMNESIA = 0x85 +MOVE_KINESIS = 0x86 +MOVE_SOFTBOILED = 0x87 +MOVE_HI_JUMP_KICK = 0x88 +MOVE_GLARE = 0x89 +MOVE_DREAM_EATER = 0x8a +MOVE_POISON_GAS = 0x8b +MOVE_BARRAGE = 0x8c +MOVE_LEECH_LIFE = 0x8d +MOVE_LOVELY_KISS = 0x8e +MOVE_SKY_ATTACK = 0x8f +MOVE_TRANSFORM = 0x90 +MOVE_BUBBLE = 0x91 +MOVE_DIZZY_PUNCH = 0x92 +MOVE_SPORE = 0x93 +MOVE_FLASH = 0x94 +MOVE_PSYWAVE = 0x95 +MOVE_SPLASH = 0x96 +MOVE_ACID_ARMOR = 0x97 +MOVE_CRABHAMMER = 0x98 +MOVE_EXPLOSION = 0x99 +MOVE_FURY_SWIPES = 0x9a +MOVE_BONEMERANG = 0x9b +MOVE_REST = 0x9c +MOVE_ROCK_SLIDE = 0x9d +MOVE_HYPER_FANG = 0x9e +MOVE_SHARPEN = 0x9f +MOVE_CONVERSION = 0xa0 +MOVE_TRI_ATTACK = 0xa1 +MOVE_SUPER_FANG = 0xa2 +MOVE_SLASH = 0xa3 +MOVE_SUBSTITUTE = 0xa4 + +MONSTER_RHYDON = 0x01 +MONSTER_KANGASKHAN = 0x02 +MONSTER_NIDORAN_M = 0x03 +MONSTER_CLEFAIRY = 0x04 +MONSTER_SPEAROW = 0x05 +MONSTER_VOLTORB = 0x06 +MONSTER_NIDOKING = 0x07 +MONSTER_SLOWBRO = 0x08 +MONSTER_IVYSAUR = 0x09 +MONSTER_EXEGGUTOR = 0x0A +MONSTER_LICKITUNG = 0x0B +MONSTER_EXEGGCUTE = 0x0C +MONSTER_GRIMER = 0x0D +MONSTER_GENGAR = 0x0E +MONSTER_NIDORAN_F = 0x0F +MONSTER_NIDOQUEEN = 0x10 +MONSTER_CUBONE = 0x11 +MONSTER_RHYHORN = 0x12 +MONSTER_LAPRAS = 0x13 +MONSTER_ARCANINE = 0x14 +MONSTER_MEW = 0x15 +MONSTER_GYARADOS = 0x16 +MONSTER_SHELLDER = 0x17 +MONSTER_TENTACOOL = 0x18 +MONSTER_GASTLY = 0x19 +MONSTER_SCYTHER = 0x1A +MONSTER_STARYU = 0x1B +MONSTER_BLASTOISE = 0x1C +MONSTER_PINSIR = 0x1D +MONSTER_TANGELA = 0x1E +MONSTER_MISSINGNO_1F = 0x1F +MONSTER_MISSINGNO_20 = 0x20 +MONSTER_GROWLITHE = 0x21 +MONSTER_ONIX = 0x22 +MONSTER_FEAROW = 0x23 +MONSTER_PIDGEY = 0x24 +MONSTER_SLOWPOKE = 0x25 +MONSTER_KADABRA = 0x26 +MONSTER_GRAVELER = 0x27 +MONSTER_CHANSEY = 0x28 +MONSTER_MACHOKE = 0x29 +MONSTER_MR_MIME = 0x2A +MONSTER_HITMONLEE = 0x2B +MONSTER_HITMONCHAN = 0x2C +MONSTER_ARBOK = 0x2D +MONSTER_PARASECT = 0x2E +MONSTER_PSYDUCK = 0x2F +MONSTER_DROWZEE = 0x30 +MONSTER_GOLEM = 0x31 +MONSTER_MISSINGNO_32 = 0x32 +MONSTER_MAGMAR = 0x33 +MONSTER_MISSINGNO_34 = 0x34 +MONSTER_ELECTABUZZ = 0x35 +MONSTER_MAGNETON = 0x36 +MONSTER_KOFFING = 0x37 +MONSTER_MISSINGNO_38 = 0x38 +MONSTER_MANKEY = 0x39 +MONSTER_SEEL = 0x3A +MONSTER_DIGLETT = 0x3B +MONSTER_TAUROS = 0x3C +MONSTER_MISSINGNO_3D = 0x3D +MONSTER_MISSINGNO_3E = 0x3E +MONSTER_MISSINGNO_3F = 0x3F +MONSTER_FARFETCHD = 0x40 +MONSTER_VENONAT = 0x41 +MONSTER_DRAGONITE = 0x42 +MONSTER_MISSINGNO_43 = 0x43 +MONSTER_MISSINGNO_44 = 0x44 +MONSTER_MISSINGNO_45 = 0x45 +MONSTER_DODUO = 0x46 +MONSTER_POLIWAG = 0x47 +MONSTER_JYNX = 0x48 +MONSTER_MOLTRES = 0x49 +MONSTER_ARTICUNO = 0x4A +MONSTER_ZAPDOS = 0x4B +MONSTER_DITTO = 0x4C +MONSTER_MEOWTH = 0x4D +MONSTER_KRABBY = 0x4E +MONSTER_MISSINGNO_4F = 0x4F +MONSTER_MISSINGNO_50 = 0x50 +MONSTER_MISSINGNO_51 = 0x51 +MONSTER_VULPIX = 0x52 +MONSTER_NINETALES = 0x53 +MONSTER_PIKACHU = 0x54 +MONSTER_RAICHU = 0x55 +MONSTER_MISSINGNO_56 = 0x56 +MONSTER_MISSINGNO_57 = 0x57 +MONSTER_DRATINI = 0x58 +MONSTER_DRAGONAIR = 0x59 +MONSTER_KABUTO = 0x5A +MONSTER_KABUTOPS = 0x5B +MONSTER_HORSEA = 0x5C +MONSTER_SEADRA = 0x5D +MONSTER_MISSINGNO_5E = 0x5E +MONSTER_MISSINGNO_5F = 0x5F +MONSTER_SANDSHREW = 0x60 +MONSTER_SANDSLASH = 0x61 +MONSTER_OMANYTE = 0x62 +MONSTER_OMASTAR = 0x63 +MONSTER_JIGGLYPUFF = 0x64 +MONSTER_WIGGLYTUFF = 0x65 +MONSTER_EEVEE = 0x66 +MONSTER_FLAREON = 0x67 +MONSTER_JOLTEON = 0x68 +MONSTER_VAPOREON = 0x69 +MONSTER_MACHOP = 0x6A +MONSTER_ZUBAT = 0x6B +MONSTER_EKANS = 0x6C +MONSTER_PARAS = 0x6D +MONSTER_POLIWHIRL = 0x6E +MONSTER_POLIWRATH = 0x6F +MONSTER_WEEDLE = 0x70 +MONSTER_KAKUNA = 0x71 +MONSTER_BEEDRILL = 0x72 +MONSTER_MISSINGNO_73 = 0x73 +MONSTER_DODRIO = 0x74 +MONSTER_PRIMEAPE = 0x75 +MONSTER_DUGTRIO = 0x76 +MONSTER_VENOMOTH = 0x77 +MONSTER_DEWGONG = 0x78 +MONSTER_MISSINGNO_79 = 0x79 +MONSTER_MISSINGNO_7A = 0x7A +MONSTER_CATERPIE = 0x7B +MONSTER_METAPOD = 0x7C +MONSTER_BUTTERFREE = 0x7D +MONSTER_MACHAMP = 0x7E +MONSTER_MISSINGNO_7F = 0x7F +MONSTER_GOLDUCK = 0x80 +MONSTER_HYPNO = 0x81 +MONSTER_GOLBAT = 0x82 +MONSTER_MEWTWO = 0x83 +MONSTER_SNORLAX = 0x84 +MONSTER_MAGIKARP = 0x85 +MONSTER_MISSINGNO_86 = 0x86 +MONSTER_MISSINGNO_87 = 0x87 +MONSTER_MUK = 0x88 +MONSTER_MISSINGNO_89 = 0x89 +MONSTER_KINGLER = 0x8A +MONSTER_CLOYSTER = 0x8B +MONSTER_MISSINGNO_8C = 0x8C +MONSTER_ELECTRODE = 0x8D +MONSTER_CLEFABLE = 0x8E +MONSTER_WEEZING = 0x8F +MONSTER_PERSIAN = 0x90 +MONSTER_MAROWAK = 0x91 +MONSTER_MISSINGNO_92 = 0x92 +MONSTER_HAUNTER = 0x93 +MONSTER_ABRA = 0x94 +MONSTER_ALAKAZAM = 0x95 +MONSTER_PIDGEOTTO = 0x96 +MONSTER_PIDGEOT = 0x97 +MONSTER_STARMIE = 0x98 +MONSTER_BULBASAUR = 0x99 +MONSTER_VENUSAUR = 0x9A +MONSTER_TENTACRUEL = 0x9B +MONSTER_MISSINGNO_9C = 0x9C +MONSTER_GOLDEEN = 0x9D +MONSTER_SEAKING = 0x9E +MONSTER_MISSINGNO_9F = 0x9F +MONSTER_MISSINGNO_A0 = 0xA0 +MONSTER_MISSINGNO_A1 = 0xA1 +MONSTER_MISSINGNO_A2 = 0xA2 +MONSTER_PONYTA = 0xA3 +MONSTER_RAPIDASH = 0xA4 +MONSTER_RATTATA = 0xA5 +MONSTER_RATICATE = 0xA6 +MONSTER_NIDORINO = 0xA7 +MONSTER_NIDORINA = 0xA8 +MONSTER_GEODUDE = 0xA9 +MONSTER_PORYGON = 0xAA +MONSTER_AERODACTYL = 0xAB +MONSTER_MISSINGNO_AC = 0xAC +MONSTER_MAGNEMITE = 0xAD +MONSTER_MISSINGNO_AE = 0xAE +MONSTER_MISSINGNO_AF = 0xAF +MONSTER_CHARMANDER = 0xB0 +MONSTER_SQUIRTLE = 0xB1 +MONSTER_CHARMELEON = 0xB2 +MONSTER_WARTORTLE = 0xB3 +MONSTER_CHARIZARD = 0xB4 +MONSTER_MISSINGNO_B5 = 0xB5 +MONSTER_FOSSIL_KABUTOPS = 0xB6 +MONSTER_FOSSIL_AERODACTYL = 0xB7 +MONSTER_MON_GHOST = 0xB8 +MONSTER_ODDISH = 0xB9 +MONSTER_GLOOM = 0xBA +MONSTER_VILEPLUME = 0xBB +MONSTER_BELLSPROUT = 0xBC +MONSTER_WEEPINBELL = 0xBD +MONSTER_VICTREEBEL = 0xBE + +ITEM_MASTER_BALL = 0x01 +ITEM_ULTRA_BALL = 0x02 +ITEM_GREAT_BALL = 0x03 +ITEM_POKE_BALL = 0x04 +ITEM_TOWN_MAP = 0x05 +ITEM_BICYCLE = 0x06 +ITEM_SURFBOARD = 0x07 +ITEM_SAFARI_BALL = 0x08 +ITEM_POKEDEX = 0x09 +ITEM_MOON_STONE = 0x0A +ITEM_ANTIDOTE = 0x0B +ITEM_BURN_HEAL = 0x0C +ITEM_ICE_HEAL = 0x0D +ITEM_AWAKENING = 0x0E +ITEM_PARLYZ_HEAL = 0x0F +ITEM_FULL_RESTORE = 0x10 +ITEM_MAX_POTION = 0x11 +ITEM_HYPER_POTION = 0x12 +ITEM_SUPER_POTION = 0x13 +ITEM_POTION = 0x14 +ITEM_BOULDERBADGE = 0x15 +ITEM_CASCADEBADGE = 0x16 +ITEM_THUNDERBADGE = 0x17 +ITEM_RAINBOWBADGE = 0x18 +ITEM_SOULBADGE = 0x19 +ITEM_MARSHBADGE = 0x1A +ITEM_VOLCANOBADGE = 0x1B +ITEM_EARTHBADGE = 0x1C +ITEM_ESCAPE_ROPE = 0x1D +ITEM_REPEL = 0x1E +ITEM_OLD_AMBER = 0x1F +ITEM_FIRE_STONE = 0x20 +ITEM_THUNDER_STONE = 0x21 +ITEM_WATER_STONE = 0x22 +ITEM_HP_UP = 0x23 +ITEM_PROTEIN = 0x24 +ITEM_IRON = 0x25 +ITEM_CARBOS = 0x26 +ITEM_CALCIUM = 0x27 +ITEM_RARE_CANDY = 0x28 +ITEM_DOME_FOSSIL = 0x29 +ITEM_HELIX_FOSSIL = 0x2A +ITEM_SECRET_KEY = 0x2B +ITEM_UNUSED_ITEM = 0x2C +ITEM_BIKE_VOUCHER = 0x2D +ITEM_X_ACCURACY = 0x2E +ITEM_LEAF_STONE = 0x2F +ITEM_CARD_KEY = 0x30 +ITEM_NUGGET = 0x31 +ITEM_PP_UP_2 = 0x32 +ITEM_POKE_DOLL = 0x33 +ITEM_FULL_HEAL = 0x34 +ITEM_REVIVE = 0x35 +ITEM_MAX_REVIVE = 0x36 +ITEM_GUARD_SPEC = 0x37 +ITEM_SUPER_REPEL = 0x38 +ITEM_MAX_REPEL = 0x39 +ITEM_DIRE_HIT = 0x3A +ITEM_COIN = 0x3B +ITEM_FRESH_WATER = 0x3C +ITEM_SODA_POP = 0x3D +ITEM_LEMONADE = 0x3E +ITEM_S_S_TICKET = 0x3F +ITEM_GOLD_TEETH = 0x40 +ITEM_X_ATTACK = 0x41 +ITEM_X_DEFEND = 0x42 +ITEM_X_SPEED = 0x43 +ITEM_X_SPECIAL = 0x44 +ITEM_COIN_CASE = 0x45 +ITEM_OAKS_PARCEL = 0x46 +ITEM_ITEMFINDER = 0x47 +ITEM_SILPH_SCOPE = 0x48 +ITEM_POKE_FLUTE = 0x49 +ITEM_LIFT_KEY = 0x4A +ITEM_EXP_ALL = 0x4B +ITEM_OLD_ROD = 0x4C +ITEM_GOOD_ROD = 0x4D +ITEM_SUPER_ROD = 0x4E +ITEM_PP_UP = 0x4F +ITEM_ETHER = 0x50 +ITEM_MAX_ETHER = 0x51 +ITEM_ELIXER = 0x52 +ITEM_MAX_ELIXER = 0x53 +ITEM_FLOOR_B2F = 0x54 +ITEM_FLOOR_B1F = 0x55 +ITEM_FLOOR_1F = 0x56 +ITEM_FLOOR_2F = 0x57 +ITEM_FLOOR_3F = 0x58 +ITEM_FLOOR_4F = 0x59 +ITEM_FLOOR_5F = 0x5A +ITEM_FLOOR_6F = 0x5B +ITEM_FLOOR_7F = 0x5C +ITEM_FLOOR_8F = 0x5D +ITEM_FLOOR_9F = 0x5E +ITEM_FLOOR_10F = 0x5F +ITEM_FLOOR_11F = 0x60 +ITEM_FLOOR_B4F = 0x61 +ITEM_HM_01 = 0xC4 +ITEM_HM_02 = 0xC5 +ITEM_HM_03 = 0xC6 +ITEM_HM_04 = 0xC7 +ITEM_HM_05 = 0xC8 +ITEM_TM_01 = 0xC9 +ITEM_TM_02 = 0xCA +ITEM_TM_03 = 0xCB +ITEM_TM_04 = 0xCC +ITEM_TM_05 = 0xCD +ITEM_TM_06 = 0xCE +ITEM_TM_07 = 0xCF +ITEM_TM_08 = 0xD0 +ITEM_TM_09 = 0xD1 +ITEM_TM_10 = 0xD2 +ITEM_TM_11 = 0xD3 +ITEM_TM_12 = 0xD4 +ITEM_TM_13 = 0xD5 +ITEM_TM_14 = 0xD6 +ITEM_TM_15 = 0xD7 +ITEM_TM_16 = 0xD8 +ITEM_TM_17 = 0xD9 +ITEM_TM_18 = 0xDA +ITEM_TM_19 = 0xDB +ITEM_TM_20 = 0xDC +ITEM_TM_21 = 0xDD +ITEM_TM_22 = 0xDE +ITEM_TM_23 = 0xDF +ITEM_TM_24 = 0xE0 +ITEM_TM_25 = 0xE1 +ITEM_TM_26 = 0xE2 +ITEM_TM_27 = 0xE3 +ITEM_TM_28 = 0xE4 +ITEM_TM_29 = 0xE5 +ITEM_TM_30 = 0xE6 +ITEM_TM_31 = 0xE7 +ITEM_TM_32 = 0xE8 +ITEM_TM_33 = 0xE9 +ITEM_TM_34 = 0xEA +ITEM_TM_35 = 0xEB +ITEM_TM_36 = 0xEC +ITEM_TM_37 = 0xED +ITEM_TM_38 = 0xEE +ITEM_TM_39 = 0xEF +ITEM_TM_40 = 0xF0 +ITEM_TM_41 = 0xF1 +ITEM_TM_42 = 0xF2 +ITEM_TM_43 = 0xF3 +ITEM_TM_44 = 0xF4 +ITEM_TM_45 = 0xF5 +ITEM_TM_46 = 0xF6 +ITEM_TM_47 = 0xF7 +ITEM_TM_48 = 0xF8 +ITEM_TM_49 = 0xF9 +ITEM_TM_50 = 0xFA + +SPRITE_RED = 0x01 +SPRITE_BLUE = 0x02 +SPRITE_OAK = 0x03 +SPRITE_BUG_CATCHER = 0x04 +SPRITE_SLOWBRO = 0x05 +SPRITE_LASS = 0x06 +SPRITE_BLACK_HAIR_BOY_1 = 0x07 +SPRITE_LITTLE_GIRL = 0x08 +SPRITE_BIRD = 0x09 +SPRITE_FAT_BALD_GUY = 0x0a +SPRITE_GAMBLER = 0x0b +SPRITE_BLACK_HAIR_BOY_2 = 0x0c +SPRITE_GIRL = 0x0d +SPRITE_HIKER = 0x0e +SPRITE_FOULARD_WOMAN = 0x0f +SPRITE_GENTLEMAN = 0x10 +SPRITE_DAISY = 0x11 +SPRITE_BIKER = 0x12 +SPRITE_SAILOR = 0x13 +SPRITE_COOK = 0x14 +SPRITE_BIKE_SHOP_GUY = 0x15 +SPRITE_MR_FUJI = 0x16 +SPRITE_GIOVANNI = 0x17 +SPRITE_ROCKET = 0x18 +SPRITE_MEDIUM = 0x19 +SPRITE_WAITER = 0x1a +SPRITE_ERIKA = 0x1b +SPRITE_MOM_GEISHA = 0x1c +SPRITE_BRUNETTE_GIRL = 0x1d +SPRITE_LANCE = 0x1e +SPRITE_OAK_SCIENTIST_AIDE = 0x1f +SPRITE_OAK_AIDE = 0x20 +SPRITE_ROCKER = 0x21 +SPRITE_SWIMMER = 0x22 +SPRITE_WHITE_PLAYER = 0x23 +SPRITE_GYM_HELPER = 0x24 +SPRITE_OLD_PERSON = 0x25 +SPRITE_MART_GUY = 0x26 +SPRITE_FISHER = 0x27 +SPRITE_OLD_MEDIUM_WOMAN = 0x28 +SPRITE_NURSE = 0x29 +SPRITE_CABLE_CLUB_WOMAN = 0x2a +SPRITE_MR_MASTERBALL = 0x2b +SPRITE_LAPRAS_GIVER = 0x2c +SPRITE_WARDEN = 0x2d +SPRITE_SS_CAPTAIN = 0x2e +SPRITE_FISHER2 = 0x2f +SPRITE_BLACKBELT = 0x30 +SPRITE_GUARD = 0x31 +SPRITE_COP_GUARD = 0x32 +SPRITE_MOM = 0x33 +SPRITE_BALDING_GUY = 0x34 +SPRITE_YOUNG_BOY = 0x35 +SPRITE_GAMEBOY_KID = 0x36 +SPRITE_GAMEBOY_KID_COPY = 0x37 +SPRITE_CLEFAIRY = 0x38 +SPRITE_AGATHA = 0x39 +SPRITE_BRUNO = 0x3a +SPRITE_LORELEI = 0x3b +SPRITE_SEEL = 0x3c +SPRITE_BALL = 0x3d +SPRITE_OMANYTE = 0x3e +SPRITE_BOULDER = 0x3f +SPRITE_PAPER_SHEET = 0x40 +SPRITE_BOOK_MAP_DEX = 0x41 +SPRITE_CLIPBOARD = 0x42 +SPRITE_SNORLAX = 0x43 +SPRITE_OLD_AMBER_COPY = 0x44 +SPRITE_OLD_AMBER = 0x45 +SPRITE_LYING_OLD_MAN_UNUSED_1 = 0x46 +SPRITE_LYING_OLD_MAN_UNUSED_2 = 0x47 +SPRITE_LYING_OLD_MAN = 0x48 + +MAP_PALLET_TOWN = 0x00 +MAP_VIRIDIAN_CITY = 0x01 +MAP_PEWTER_CITY = 0x02 +MAP_CERULEAN_CITY = 0x03 +MAP_LAVENDER_TOWN = 0x04 +MAP_VERMILION_CITY = 0x05 +MAP_CELADON_CITY = 0x06 +MAP_FUCHSIA_CITY = 0x07 +MAP_CINNABAR_ISLAND = 0x08 +MAP_INDIGO_PLATEAU = 0x09 +MAP_SAFFRON_CITY = 0x0A +MAP_UNUSED_MAP_0B = 0x0B +MAP_ROUTE_1 = 0x0C +MAP_ROUTE_2 = 0x0D +MAP_ROUTE_3 = 0x0E +MAP_ROUTE_4 = 0x0F +MAP_ROUTE_5 = 0x10 +MAP_ROUTE_6 = 0x11 +MAP_ROUTE_7 = 0x12 +MAP_ROUTE_8 = 0x13 +MAP_ROUTE_9 = 0x14 +MAP_ROUTE_10 = 0x15 +MAP_ROUTE_11 = 0x16 +MAP_ROUTE_12 = 0x17 +MAP_ROUTE_13 = 0x18 +MAP_ROUTE_14 = 0x19 +MAP_ROUTE_15 = 0x1A +MAP_ROUTE_16 = 0x1B +MAP_ROUTE_17 = 0x1C +MAP_ROUTE_18 = 0x1D +MAP_ROUTE_19 = 0x1E +MAP_ROUTE_20 = 0x1F +MAP_ROUTE_21 = 0x20 +MAP_ROUTE_22 = 0x21 +MAP_ROUTE_23 = 0x22 +MAP_ROUTE_24 = 0x23 +MAP_ROUTE_25 = 0x24 +MAP_REDS_HOUSE_1F = 0x25 +MAP_REDS_HOUSE_2F = 0x26 +MAP_BLUES_HOUSE = 0x27 +MAP_OAKS_LAB = 0x28 +MAP_VIRIDIAN_POKECENTER = 0x29 +MAP_VIRIDIAN_MART = 0x2A +MAP_VIRIDIAN_SCHOOL_HOUSE = 0x2B +MAP_VIRIDIAN_NICKNAME_HOUSE = 0x2C +MAP_VIRIDIAN_GYM = 0x2D +MAP_DIGLETTS_CAVE_ROUTE_2 = 0x2E +MAP_VIRIDIAN_FOREST_NORTH_GATE = 0x2F +MAP_ROUTE_2_TRADE_HOUSE = 0x30 +MAP_ROUTE_2_GATE = 0x31 +MAP_VIRIDIAN_FOREST_SOUTH_GATE = 0x32 +MAP_VIRIDIAN_FOREST = 0x33 +MAP_MUSEUM_1F = 0x34 +MAP_MUSEUM_2F = 0x35 +MAP_PEWTER_GYM = 0x36 +MAP_PEWTER_NIDORAN_HOUSE = 0x37 +MAP_PEWTER_MART = 0x38 +MAP_PEWTER_SPEECH_HOUSE = 0x39 +MAP_PEWTER_POKECENTER = 0x3A +MAP_MT_MOON_1F = 0x3B +MAP_MT_MOON_B1F = 0x3C +MAP_MT_MOON_B2F = 0x3D +MAP_CERULEAN_TRASHED_HOUSE = 0x3E +MAP_CERULEAN_TRADE_HOUSE = 0x3F +MAP_CERULEAN_POKECENTER = 0x40 +MAP_CERULEAN_GYM = 0x41 +MAP_BIKE_SHOP = 0x42 +MAP_CERULEAN_MART = 0x43 +MAP_MT_MOON_POKECENTER = 0x44 +MAP_CERULEAN_TRASHED_HOUSE_COPY = 0x45 +MAP_ROUTE_5_GATE = 0x46 +MAP_UNDERGROUND_PATH_ROUTE_5 = 0x47 +MAP_DAYCARE = 0x48 +MAP_ROUTE_6_GATE = 0x49 +MAP_UNDERGROUND_PATH_ROUTE_6 = 0x4A +MAP_UNDERGROUND_PATH_ROUTE_6_COPY = 0x4B +MAP_ROUTE_7_GATE = 0x4C +MAP_UNDERGROUND_PATH_ROUTE_7 = 0x4D +MAP_UNDERGROUND_PATH_ROUTE_7_COPY = 0x4E +MAP_ROUTE_8_GATE = 0x4F +MAP_UNDERGROUND_PATH_ROUTE_8 = 0x50 +MAP_ROCK_TUNNEL_POKECENTER = 0x51 +MAP_ROCK_TUNNEL_1F = 0x52 +MAP_POWER_PLANT = 0x53 +MAP_ROUTE_11_GATE_1F = 0x54 +MAP_DIGLETTS_CAVE_ROUTE_11 = 0x55 +MAP_ROUTE_11_GATE_2F = 0x56 +MAP_ROUTE_12_GATE_1F = 0x57 +MAP_BILLS_HOUSE = 0x58 +MAP_VERMILION_POKECENTER = 0x59 +MAP_POKEMON_FAN_CLUB = 0x5A +MAP_VERMILION_MART = 0x5B +MAP_VERMILION_GYM = 0x5C +MAP_VERMILION_PIDGEY_HOUSE = 0x5D +MAP_VERMILION_DOCK = 0x5E +MAP_SS_ANNE_1F = 0x5F +MAP_SS_ANNE_2F = 0x60 +MAP_SS_ANNE_3F = 0x61 +MAP_SS_ANNE_B1F = 0x62 +MAP_SS_ANNE_BOW = 0x63 +MAP_SS_ANNE_KITCHEN = 0x64 +MAP_SS_ANNE_CAPTAINS_ROOM = 0x65 +MAP_SS_ANNE_1F_ROOMS = 0x66 +MAP_SS_ANNE_2F_ROOMS = 0x67 +MAP_SS_ANNE_B1F_ROOMS = 0x68 +MAP_UNUSED_MAP_69 = 0x69 +MAP_UNUSED_MAP_6A = 0x6A +MAP_UNUSED_MAP_6B = 0x6B +MAP_VICTORY_ROAD_1F = 0x6C +MAP_UNUSED_MAP_6D = 0x6D +MAP_UNUSED_MAP_6E = 0x6E +MAP_UNUSED_MAP_6F = 0x6F +MAP_UNUSED_MAP_70 = 0x70 +MAP_LANCES_ROOM = 0x71 +MAP_UNUSED_MAP_72 = 0x72 +MAP_UNUSED_MAP_73 = 0x73 +MAP_UNUSED_MAP_74 = 0x74 +MAP_UNUSED_MAP_75 = 0x75 +MAP_HALL_OF_FAME = 0x76 +MAP_UNDERGROUND_PATH_NORTH_SOUTH = 0x77 +MAP_CHAMPIONS_ROOM = 0x78 +MAP_UNDERGROUND_PATH_WEST_EAST = 0x79 +MAP_CELADON_MART_1F = 0x7A +MAP_CELADON_MART_2F = 0x7B +MAP_CELADON_MART_3F = 0x7C +MAP_CELADON_MART_4F = 0x7D +MAP_CELADON_MART_ROOF = 0x7E +MAP_CELADON_MART_ELEVATOR = 0x7F +MAP_CELADON_MANSION_1F = 0x80 +MAP_CELADON_MANSION_2F = 0x81 +MAP_CELADON_MANSION_3F = 0x82 +MAP_CELADON_MANSION_ROOF = 0x83 +MAP_CELADON_MANSION_ROOF_HOUSE = 0x84 +MAP_CELADON_POKECENTER = 0x85 +MAP_CELADON_GYM = 0x86 +MAP_GAME_CORNER = 0x87 +MAP_CELADON_MART_5F = 0x88 +MAP_GAME_CORNER_PRIZE_ROOM = 0x89 +MAP_CELADON_DINER = 0x8A +MAP_CELADON_CHIEF_HOUSE = 0x8B +MAP_CELADON_HOTEL = 0x8C +MAP_LAVENDER_POKECENTER = 0x8D +MAP_POKEMON_TOWER_1F = 0x8E +MAP_POKEMON_TOWER_2F = 0x8F +MAP_POKEMON_TOWER_3F = 0x90 +MAP_POKEMON_TOWER_4F = 0x91 +MAP_POKEMON_TOWER_5F = 0x92 +MAP_POKEMON_TOWER_6F = 0x93 +MAP_POKEMON_TOWER_7F = 0x94 +MAP_MR_FUJIS_HOUSE = 0x95 +MAP_LAVENDER_MART = 0x96 +MAP_LAVENDER_CUBONE_HOUSE = 0x97 +MAP_FUCHSIA_MART = 0x98 +MAP_FUCHSIA_BILLS_GRANDPAS_HOUSE = 0x99 +MAP_FUCHSIA_POKECENTER = 0x9A +MAP_WARDENS_HOUSE = 0x9B +MAP_SAFARI_ZONE_GATE = 0x9C +MAP_FUCHSIA_GYM = 0x9D +MAP_FUCHSIA_MEETING_ROOM = 0x9E +MAP_SEAFOAM_ISLANDS_B1F = 0x9F +MAP_SEAFOAM_ISLANDS_B2F = 0xA0 +MAP_SEAFOAM_ISLANDS_B3F = 0xA1 +MAP_SEAFOAM_ISLANDS_B4F = 0xA2 +MAP_VERMILION_OLD_ROD_HOUSE = 0xA3 +MAP_FUCHSIA_GOOD_ROD_HOUSE = 0xA4 +MAP_POKEMON_MANSION_1F = 0xA5 +MAP_CINNABAR_GYM = 0xA6 +MAP_CINNABAR_LAB = 0xA7 +MAP_CINNABAR_LAB_TRADE_ROOM = 0xA8 +MAP_CINNABAR_LAB_METRONOME_ROOM = 0xA9 +MAP_CINNABAR_LAB_FOSSIL_ROOM = 0xAA +MAP_CINNABAR_POKECENTER = 0xAB +MAP_CINNABAR_MART = 0xAC +MAP_CINNABAR_MART_COPY = 0xAD +MAP_INDIGO_PLATEAU_LOBBY = 0xAE +MAP_COPYCATS_HOUSE_1F = 0xAF +MAP_COPYCATS_HOUSE_2F = 0xB0 +MAP_FIGHTING_DOJO = 0xB1 +MAP_SAFFRON_GYM = 0xB2 +MAP_SAFFRON_PIDGEY_HOUSE = 0xB3 +MAP_SAFFRON_MART = 0xB4 +MAP_SILPH_CO_1F = 0xB5 +MAP_SAFFRON_POKECENTER = 0xB6 +MAP_MR_PSYCHICS_HOUSE = 0xB7 +MAP_ROUTE_15_GATE_1F = 0xB8 +MAP_ROUTE_15_GATE_2F = 0xB9 +MAP_ROUTE_16_GATE_1F = 0xBA +MAP_ROUTE_16_GATE_2F = 0xBB +MAP_ROUTE_16_FLY_HOUSE = 0xBC +MAP_ROUTE_12_SUPER_ROD_HOUSE = 0xBD +MAP_ROUTE_18_GATE_1F = 0xBE +MAP_ROUTE_18_GATE_2F = 0xBF +MAP_SEAFOAM_ISLANDS_1F = 0xC0 +MAP_ROUTE_22_GATE = 0xC1 +MAP_VICTORY_ROAD_2F = 0xC2 +MAP_ROUTE_12_GATE_2F = 0xC3 +MAP_VERMILION_TRADE_HOUSE = 0xC4 +MAP_DIGLETTS_CAVE = 0xC5 +MAP_VICTORY_ROAD_3F = 0xC6 +MAP_ROCKET_HIDEOUT_B1F = 0xC7 +MAP_ROCKET_HIDEOUT_B2F = 0xC8 +MAP_ROCKET_HIDEOUT_B3F = 0xC9 +MAP_ROCKET_HIDEOUT_B4F = 0xCA +MAP_ROCKET_HIDEOUT_ELEVATOR = 0xCB +MAP_UNUSED_MAP_CC = 0xCC +MAP_UNUSED_MAP_CD = 0xCD +MAP_UNUSED_MAP_CE = 0xCE +MAP_SILPH_CO_2F = 0xCF +MAP_SILPH_CO_3F = 0xD0 +MAP_SILPH_CO_4F = 0xD1 +MAP_SILPH_CO_5F = 0xD2 +MAP_SILPH_CO_6F = 0xD3 +MAP_SILPH_CO_7F = 0xD4 +MAP_SILPH_CO_8F = 0xD5 +MAP_POKEMON_MANSION_2F = 0xD6 +MAP_POKEMON_MANSION_3F = 0xD7 +MAP_POKEMON_MANSION_B1F = 0xD8 +MAP_SAFARI_ZONE_EAST = 0xD9 +MAP_SAFARI_ZONE_NORTH = 0xDA +MAP_SAFARI_ZONE_WEST = 0xDB +MAP_SAFARI_ZONE_CENTER = 0xDC +MAP_SAFARI_ZONE_CENTER_REST_HOUSE = 0xDD +MAP_SAFARI_ZONE_SECRET_HOUSE = 0xDE +MAP_SAFARI_ZONE_WEST_REST_HOUSE = 0xDF +MAP_SAFARI_ZONE_EAST_REST_HOUSE = 0xE0 +MAP_SAFARI_ZONE_NORTH_REST_HOUSE = 0xE1 +MAP_CERULEAN_CAVE_2F = 0xE2 +MAP_CERULEAN_CAVE_B1F = 0xE3 +MAP_CERULEAN_CAVE_1F = 0xE4 +MAP_NAME_RATERS_HOUSE = 0xE5 +MAP_CERULEAN_BADGE_HOUSE = 0xE6 +MAP_UNUSED_MAP_E7 = 0xE7 +MAP_ROCK_TUNNEL_B1F = 0xE8 +MAP_SILPH_CO_9F = 0xE9 +MAP_SILPH_CO_10F = 0xEA +MAP_SILPH_CO_11F = 0xEB +MAP_SILPH_CO_ELEVATOR = 0xEC +MAP_UNUSED_MAP_ED = 0xED +MAP_UNUSED_MAP_EE = 0xEE +MAP_TRADE_CENTER = 0xEF +MAP_COLOSSEUM = 0xF0 +MAP_UNUSED_MAP_F1 = 0xF1 +MAP_UNUSED_MAP_F2 = 0xF2 +MAP_UNUSED_MAP_F3 = 0xF3 +MAP_UNUSED_MAP_F4 = 0xF4 +MAP_LORELEIS_ROOM = 0xF5 +MAP_BRUNOS_ROOM = 0xF6 +MAP_AGATHAS_ROOM = 0xF7 + +MAP_NAMES = [ +'PALLET TOWN', +'VIRIDIAN CITY', +'PEWTER CITY', +'CERULEAN CITY', +'LAVENDER TOWN', +'VERMILION CITY', +'CELADON CITY', +'FUCHSIA CITY', +'CINNABAR ISLAND', +'INDIGO PLATEAU', +'SAFFRON CITY', +'UNUSED MAP 0B', +'ROUTE 1', +'ROUTE 2', +'ROUTE 3', +'ROUTE 4', +'ROUTE 5', +'ROUTE 6', +'ROUTE 7', +'ROUTE 8', +'ROUTE 9', +'ROUTE 10', +'ROUTE 11', +'ROUTE 12', +'ROUTE 13', +'ROUTE 14', +'ROUTE 15', +'ROUTE 16', +'ROUTE 17', +'ROUTE 18', +'ROUTE 19', +'ROUTE 20', +'ROUTE 21', +'ROUTE 22', +'ROUTE 23', +'ROUTE 24', +'ROUTE 25', +'RED\'S HOUSE 1F', +'RED\'S HOUSE 2F', +'BLUE\'S HOUSE', +'OAK\'S LAB', +'VIRIDIAN POKECENTER', +'VIRIDIAN MART', +'VIRIDIAN SCHOOL HOUSE', +'VIRIDIAN NICKNAME HOUSE', +'VIRIDIAN GYM', +'DIGLETTS CAVE ROUTE 2', +'VIRIDIAN FOREST NORTH GATE', +'ROUTE 2 TRADE HOUSE', +'ROUTE 2 GATE', +'VIRIDIAN FOREST SOUTH GATE', +'VIRIDIAN FOREST', +'MUSEUM 1F', +'MUSEUM 2F', +'PEWTER GYM', +'PEWTER NIDORAN HOUSE', +'PEWTER MART', +'PEWTER SPEECH HOUSE', +'PEWTER POKECENTER', +'MT MOON 1F', +'MT MOON B1F', +'MT MOON B2F', +'CERULEAN TRASHED HOUSE', +'CERULEAN TRADE HOUSE', +'CERULEAN POKECENTER', +'CERULEAN GYM', +'BIKE SHOP', +'CERULEAN MART', +'MT MOON POKECENTER', +'CERULEAN TRASHED HOUSE COPY', +'ROUTE 5 GATE', +'UNDERGROUND PATH ROUTE 5', +'DAYCARE', +'ROUTE 6 GATE', +'UNDERGROUND PATH ROUTE 6', +'UNDERGROUND PATH ROUTE 6 COPY', +'ROUTE 7 GATE', +'UNDERGROUND PATH ROUTE 7', +'UNDERGROUND PATH ROUTE 7 COPY', +'ROUTE 8 GATE', +'UNDERGROUND PATH ROUTE 8', +'ROCK TUNNEL POKECENTER', +'ROCK TUNNEL 1F', +'POWER PLANT', +'ROUTE 11 GATE 1F', +'DIGLETT\'S CAVE ROUTE 11', +'ROUTE 11 GATE 2F', +'ROUTE 12 GATE 1F', +'BILLS HOUSE', +'VERMILION POKECENTER', +'POKEMON FAN CLUB', +'VERMILION MART', +'VERMILION GYM', +'VERMILION PIDGEY HOUSE', +'VERMILION DOCK', +'SS ANNE 1F', +'SS ANNE 2F', +'SS ANNE 3F', +'SS ANNE B1F', +'SS ANNE BOW', +'SS ANNE KITCHEN', +'SS ANNE CAPTAIN\'S ROOM', +'SS ANNE 1F ROOMS', +'SS ANNE 2F ROOMS', +'SS ANNE B1F ROOMS', +'UNUSED MAP 69', +'UNUSED MAP 6A', +'UNUSED MAP 6B', +'VICTORY ROAD 1F', +'UNUSED MAP 6D', +'UNUSED MAP 6E', +'UNUSED MAP 6F', +'UNUSED MAP 70', +'LANCES ROOM', +'UNUSED MAP 72', +'UNUSED MAP 73', +'UNUSED MAP 74', +'UNUSED MAP 75', +'HALL OF FAME', +'UNDERGROUND PATH NORTH SOUTH', +'CHAMPION\'S ROOM', +'UNDERGROUND PATH WEST EAST', +'CELADON MART 1F', +'CELADON MART 2F', +'CELADON MART 3F', +'CELADON MART 4F', +'CELADON MART ROOF', +'CELADON MART ELEVATOR', +'CELADON MANSION 1F', +'CELADON MANSION 2F', +'CELADON MANSION 3F', +'CELADON MANSION ROOF', +'CELADON MANSION ROOF HOUSE', +'CELADON POKECENTER', +'CELADON GYM', +'GAME CORNER', +'CELADON MART 5F', +'GAME CORNER PRIZE ROOM', +'CELADON DINER', +'CELADON CHIEF HOUSE', +'CELADON HOTEL', +'LAVENDER POKECENTER', +'POKEMON TOWER 1F', +'POKEMON TOWER 2F', +'POKEMON TOWER 3F', +'POKEMON TOWER 4F', +'POKEMON TOWER 5F', +'POKEMON TOWER 6F', +'POKEMON TOWER 7F', +'MR FUJIS HOUSE', +'LAVENDER MART', +'LAVENDER CUBONE HOUSE', +'FUCHSIA MART', +'FUCHSIA BILL\'S GRANDPAS HOUSE', +'FUCHSIA POKECENTER', +'WARDENS HOUSE', +'SAFARI ZONE GATE', +'FUCHSIA GYM', +'FUCHSIA MEETING ROOM', +'SEAFOAM ISLANDS B1F', +'SEAFOAM ISLANDS B2F', +'SEAFOAM ISLANDS B3F', +'SEAFOAM ISLANDS B4F', +'VERMILION OLD ROD HOUSE', +'FUCHSIA GOOD ROD HOUSE', +'POKEMON MANSION 1F', +'CINNABAR GYM', +'CINNABAR LAB', +'CINNABAR LAB TRADE ROOM', +'CINNABAR LAB METRONOME ROOM', +'CINNABAR LAB FOSSIL ROOM', +'CINNABAR POKECENTER', +'CINNABAR MART', +'CINNABAR MART COPY', +'INDIGO PLATEAU LOBBY', +'COPYCATS HOUSE 1F', +'COPYCATS HOUSE 2F', +'FIGHTING DOJO', +'SAFFRON GYM', +'SAFFRON PIDGEY HOUSE', +'SAFFRON MART', +'SILPH CO 1F', +'SAFFRON POKECENTER', +'MR PSYCHICS HOUSE', +'ROUTE 15 GATE 1F', +'ROUTE 15 GATE 2F', +'ROUTE 16 GATE 1F', +'ROUTE 16 GATE 2F', +'ROUTE 16 FLY HOUSE', +'ROUTE 12 SUPER ROD HOUSE', +'ROUTE 18 GATE 1F', +'ROUTE 18 GATE 2F', +'SEAFOAM ISLANDS 1F', +'ROUTE 22 GATE', +'VICTORY ROAD 2F', +'ROUTE 12 GATE 2F', +'VERMILION TRADE HOUSE', +'DIGLETTS CAVE', +'VICTORY ROAD 3F', +'ROCKET HIDEOUT B1F', +'ROCKET HIDEOUT B2F', +'ROCKET HIDEOUT B3F', +'ROCKET HIDEOUT B4F', +'ROCKET HIDEOUT ELEVATOR', +'UNUSED MAP CC', +'UNUSED MAP CD', +'UNUSED MAP CE', +'SILPH CO 2F', +'SILPH CO 3F', +'SILPH CO 4F', +'SILPH CO 5F', +'SILPH CO 6F', +'SILPH CO 7F', +'SILPH CO 8F', +'POKEMON MANSION 2F', +'POKEMON MANSION 3F', +'POKEMON MANSION B1F', +'SAFARI ZONE EAST', +'SAFARI ZONE NORTH', +'SAFARI ZONE WEST', +'SAFARI ZONE CENTER', +'SAFARI ZONE CENTER REST HOUSE', +'SAFARI ZONE SECRET HOUSE', +'SAFARI ZONE WEST REST HOUSE', +'SAFARI ZONE EAST REST HOUSE', +'SAFARI ZONE NORTH REST HOUSE', +'CERULEAN CAVE 2F', +'CERULEAN CAVE B1F', +'CERULEAN CAVE 1F', +'NAME RATER\'S HOUSE', +'CERULEAN BADGE HOUSE', +'UNUSED MAP E7', +'ROCK TUNNEL B1F', +'SILPH CO 9F', +'SILPH CO 10F', +'SILPH CO 11F', +'SILPH CO ELEVATOR', +'UNUSED MAP ED', +'UNUSED MAP EE', +'TRADE CENTER', +'COLOSSEUM', +'UNUSED MAP F1', +'UNUSED MAP F2', +'UNUSED MAP F3', +'UNUSED MAP F4', +'LORELEI\'S ROOM', +'BRUNO\'S ROOM', +'AGATHA\'S ROOM', +] + +STATUS_ASLEEP = 4 +STATUS_POISONED = 8 +STATUS_BURNED = 16 +STATUS_FROZEN = 32 +STATUS_PARALYZED = 64 + +MONSTER_NAMES = ( + "Bulbasaur", + "Ivysaur", + "Venusaur", + "Charmander", + "Charmeleon", + "Charizard", + "Squirtle", + "Wartortle", + "Blastoise", + "Caterpie", + "Metapod", + "Butterfree", + "Weedle", + "Kakuna", + "Beedrill", + "Pidgey", + "Pidgeotto", + "Pidgeot", + "Rattata", + "Raticate", + "Spearow", + "Fearow", + "Ekans", + "Arbok", + "Pikachu", + "Raichu", + "Sandshrew", + "Sandslash", + "Nidoran♀", + "Nidorina", + "Nidoqueen", + "Nidoran♂", + "Nidorino", + "Nidoking", + "Clefairy", + "Clefable", + "Vulpix", + "Ninetales", + "Jigglypuff", + "Wigglytuff", + "Zubat", + "Golbat", + "Oddish", + "Gloom", + "Vileplume", + "Paras", + "Parasect", + "Venonat", + "Venomoth", + "Diglett", + "Dugtrio", + "Meowth", + "Persian", + "Psyduck", + "Golduck", + "Mankey", + "Primeape", + "Growlithe", + "Arcanine", + "Poliwag", + "Poliwhirl", + "Poliwrath", + "Abra", + "Kadabra", + "Alakazam", + "Machop", + "Machoke", + "Machamp", + "Bellsprout", + "Weepinbell", + "Victreebel", + "Tentacool", + "Tentacruel", + "Geodude", + "Graveler", + "Golem", + "Ponyta", + "Rapidash", + "Slowpoke", + "Slowbro", + "Magnemite", + "Magneton", + "Farfetch’d", + "Doduo", + "Dodrio", + "Seel", + "Dewgong", + "Grimer", + "Muk", + "Shellder", + "Cloyster", + "Gastly", + "Haunter", + "Gengar", + "Onix", + "Drowzee", + "Hypno", + "Krabby", + "Kingler", + "Voltorb", + "Electrode", + "Exeggcute", + "Exeggutor", + "Cubone", + "Marowak", + "Hitmonlee", + "Hitmonchan", + "Lickitung", + "Koffing", + "Weezing", + "Rhyhorn", + "Rhydon", + "Chansey", + "Tangela", + "Kangaskhan", + "Horsea", + "Seadra", + "Goldeen", + "Seaking", + "Staryu", + "Starmie", + "Mr. Mime", + "Scyther", + "Jynx", + "Electabuzz", + "Magmar", + "Pinsir", + "Tauros", + "Magikarp", + "Gyarados", + "Lapras", + "Ditto", + "Eevee", + "Vaporeon", + "Jolteon", + "Flareon", + "Porygon", + "Omanyte", + "Omastar", + "Kabuto", + "Kabutops", + "Aerodactyl", + "Snorlax", + "Articuno", + "Zapdos", + "Moltres", + "Dratini", + "Dragonair", + "Dragonite", + "Mewtwo", + "Mew", +) + +POKEDEX_TO_INDEX_MAP = ( + (112, 0x01), + (115, 0x02), + (32, 0x03), + (35, 0x04), + (21, 0x05), + (100, 0x06), + (34, 0x07), + (80, 0x08), + (2, 0x09), + (103, 0x0A), + (108, 0x0B), + (102, 0x0C), + (88, 0x0D), + (94, 0x0E), + (29, 0x0F), + (31, 0x10), + (104, 0x11), + (111, 0x12), + (131, 0x13), + (59, 0x14), + (151, 0x15), + (130, 0x16), + (90, 0x17), + (72, 0x18), + (92, 0x19), + (123, 0x1A), + (120, 0x1B), + (9, 0x1C), + (127, 0x1D), + (114, 0x1E), + (58, 0x21), + (95, 0x22), + (22, 0x23), + (16, 0x24), + (79, 0x25), + (64, 0x26), + (75, 0x27), + (113, 0x28), + (67, 0x29), + (122, 0x2A), + (106, 0x2B), + (107, 0x2C), + (24, 0x2D), + (47, 0x2E), + (54, 0x2F), + (96, 0x30), + (76, 0x31), + (126, 0x33), + (125, 0x35), + (82, 0x36), + (109, 0x37), + (56, 0x39), + (86, 0x3A), + (50, 0x3B), + (128, 0x3C), + (83, 0x40), + (48, 0x41), + (149, 0x42), + (84, 0x46), + (60, 0x47), + (124, 0x48), + (146, 0x49), + (144, 0x4A), + (145, 0x4B), + (132, 0x4C), + (52, 0x4D), + (98, 0x4E), + (37, 0x52), + (38, 0x53), + (25, 0x54), + (26, 0x55), + (147, 0x58), + (148, 0x59), + (140, 0x5A), + (141, 0x5B), + (116, 0x5C), + (117, 0x5D), + (27, 0x60), + (28, 0x61), + (138, 0x62), + (139, 0x63), + (39, 0x64), + (40, 0x65), + (133, 0x66), + (136, 0x67), + (135, 0x68), + (134, 0x69), + (66, 0x6A), + (41, 0x6B), + (23, 0x6C), + (46, 0x6D), + (61, 0x6E), + (62, 0x6F), + (13, 0x70), + (14, 0x71), + (15, 0x72), + (85, 0x74), + (57, 0x75), + (51, 0x76), + (49, 0x77), + (87, 0x78), + (10, 0x7B), + (11, 0x7C), + (12, 0x7D), + (68, 0x7E), + (55, 0x80), + (97, 0x81), + (42, 0x82), + (150, 0x83), + (143, 0x84), + (129, 0x85), + (89, 0x88), + (99, 0x8A), + (91, 0x8B), + (101, 0x8D), + (36, 0x8E), + (110, 0x8F), + (53, 0x90), + (105, 0x91), + (93, 0x93), + (63, 0x94), + (65, 0x95), + (17, 0x96), + (18, 0x97), + (121, 0x98), + (1, 0x99), + (2, 0x9A), + (73, 0x9B), + (118, 0x9D), + (119, 0x9E), + (77, 0xA3), + (78, 0xA4), + (19, 0xA5), + (20, 0xA6), + (33, 0xA7), + (30, 0xA8), + (74, 0xA9), + (137, 0xAA), + (142, 0xAB), + (81, 0xAD), + (4, 0xB0), + (7, 0xB1), + (5, 0xB2), + (8, 0xB3), + (6, 0xB4), + (43, 0xB9), + (44, 0xBA), + (45, 0xBB), + (69, 0xBC), + (70, 0xBD), + (71, 0xBE), +) From 3e87f78d23892f75ae4e68dac726a17727f88e35 Mon Sep 17 00:00:00 2001 From: Maciek Baron Date: Sat, 27 Jun 2020 19:33:48 +0100 Subject: [PATCH 02/74] Add initial Pokemon Red wrapper code --- .../game_wrapper_pokemon_red/__init__.py | 1 + .../plugins/game_wrapper_pokemon_red/utils.py | 17 + .../game_wrapper_pokemon_red/wrapper.py | 385 ++++++++++++++++++ 3 files changed, 403 insertions(+) create mode 100644 pyboy/plugins/game_wrapper_pokemon_red/__init__.py create mode 100644 pyboy/plugins/game_wrapper_pokemon_red/utils.py create mode 100644 pyboy/plugins/game_wrapper_pokemon_red/wrapper.py diff --git a/pyboy/plugins/game_wrapper_pokemon_red/__init__.py b/pyboy/plugins/game_wrapper_pokemon_red/__init__.py new file mode 100644 index 000000000..483ff23f9 --- /dev/null +++ b/pyboy/plugins/game_wrapper_pokemon_red/__init__.py @@ -0,0 +1 @@ +from .wrapper import GameWrapperPokemonRed diff --git a/pyboy/plugins/game_wrapper_pokemon_red/utils.py b/pyboy/plugins/game_wrapper_pokemon_red/utils.py new file mode 100644 index 000000000..77d52d432 --- /dev/null +++ b/pyboy/plugins/game_wrapper_pokemon_red/utils.py @@ -0,0 +1,17 @@ +from .constants import ASCII_DELTA + +def get_character_index(character): + if character == ' ': + return 0x7F + if character == '?': + return 0xE6 + if character == '!': + return 0xE7 + if character == 'é': + return 0xBA + + index = ord(character) + if index > 47 and index < 58: + # number + return index + 197 + return index + ASCII_DELTA diff --git a/pyboy/plugins/game_wrapper_pokemon_red/wrapper.py b/pyboy/plugins/game_wrapper_pokemon_red/wrapper.py new file mode 100644 index 000000000..b363c5455 --- /dev/null +++ b/pyboy/plugins/game_wrapper_pokemon_red/wrapper.py @@ -0,0 +1,385 @@ +# +# License: See LICENSE.md file +# GitHub: https://github.com/Baekalfen/PyBoy +# + +__pdoc__ = { + "GameWrapperPokemonRed.cartridge_title": False, + "GameWrapperPokemonRed.post_tick": False, +} + +from pyboy.utils import WindowEvent +from pyboy.logger import logger +from ..base_plugin import PyBoyGameWrapper +from . import constants +from .utils import get_character_index + +PKMN_SIZE = 0x2C +BYTE_ORDER = 'big' + + +try: + from cython import compiled + cythonmode = compiled +except ImportError: + cythonmode = False + + +class GameWrapperPokemonRed(PyBoyGameWrapper): + """ + This class wraps Pokemon Red, and provides easy access to score and a "fitness" score for AIs. + + If you call `print` on an instance of this object, it will show an overview of everything this object provides. + """ + cartridge_title = "POKEMON RED" + + def __init__(self, *args, **kwargs): + # TODO: Determine proper size + self.shape = (20, 16) + """The shape of the game area""" + super().__init__(*args, game_area_section=(0, 0) + self.shape, game_area_wrap_around=True, **kwargs) + + def start_game(self, timer_div=None): + """ + Call this function right after initializing PyBoy. This will navigate through menus to start the game at the + first playable state. + + The state of the emulator is saved, and using `reset_game`, you can get back to this point of the game + instantly. + + Kwargs: + timer_div (int): Replace timer's DIV register with this value. Use `None` to randomize. + """ + while self.get_player_name() != 'NINTEN': # Player is NINTEN on start screen + self.pyboy.tick() + self.pyboy.send_input(WindowEvent.PRESS_BUTTON_START) + self.pyboy.tick() + PyBoyGameWrapper.start_game(self, timer_div=timer_div) + + def reset_game(self, timer_div=None): + """ + After calling `start_game`, you can call this method at any time to reset the game. + + Kwargs: + timer_div (int): Replace timer's DIV register with this value. Use `None` to randomize. + """ + PyBoyGameWrapper.reset_game(self, timer_div=timer_div) + + def get_int_at_address(self, address, size=2): + """Returns an integer from a given address of a specified size.""" + bytes = [] + for i in range(size): + bytes.append(self.pyboy.get_memory_value(address + i)) + return int.from_bytes(bytes, byteorder=BYTE_ORDER) + + def set_int_at_address(self, address, value, size=2): + """Sets an integer at a given address of a specified size.""" + bytes = value.to_bytes(2, byteorder=BYTE_ORDER) + i = 0 + for byte in bytes: + self.pyboy.set_memory_value(address + i, byte) + i += 1 + + def set_text(self, text, address): + """Sets text at address. + + Will always add a string terminator (80) at the end. + """ + i = 0 + for character in text: + try: + self.pyboy.set_memory_value(address + i, get_character_index(character)) + i += 1 + except: + pass + self.pyboy.set_memory_value(address + i, constants.STRING_TERMINATOR) + + def set_rom_text(self, text, bank, address): + i = 0 + for character in text: + try: + self.pyboy.override_memory_value(bank, address + i, get_character_index(character)) + i += 1 + except: + pass + + def set_player_name(self, name): + """ + Sets the player name. + + Args: + name (string): Name to be set (will be trimmed at 8 characters). + """ + self.set_text(name[:8], 0xD158) + + def get_player_name(self): + """ + Returns player name. + """ + return self.get_text(0xD158) + + def set_rival_name(self, name): + """ + Sets the rival name. + + Args: + name (string): Name to be set (will be trimmed at 8 characters). + """ + self.set_text(name[:8], 0xD34A) + + def get_rival_name(self): + """ + Returns rival name. + """ + return self.get_text(0xD34A) + + def get_text(self, address, cap = 16): + """ + Retrieves a string from a given address. + + Args: + address (int): Address from where to retrieve text from. + cap (int): Maximum expected length of string (default: 16). + """ + i = 0 + text = '' + while i < cap: + value = self.pyboy.get_memory_value(address + i) + try: + text += chr(value - constants.ASCII_DELTA) + except: + pass + if value == constants.STRING_TERMINATOR: + break + i += 1 + return text + + def set_palette_to_darkness(self): + self.pyboy.set_memory_value(0xD35D, 6) + + def set_player_monster(self, index, monster): + """ + Sets player monster at a given index. + + Args: + index (int): Which monster to change (0-5). + monster (int): Which type of monster to set. + """ + self.pyboy.set_memory_value(0xD16B + index, monster) + self.pyboy.set_memory_value(0xD164 + (index * PKMN_SIZE), monster) + + def get_player_monster(self, index): + """ + Returns player monster at a given index. + + Args: + index (int): Which monster to change (0-5). + """ + return self.pyboy.get_memory_value(0xD16B + index) + + def set_player_monster_nickname(self, index, text): + """ + Sets player monster's nickname at a given index. + + Args: + index (int): Which monster to change (0-5). + text (string): Nickname to set (will be trimmed at 10 characters). + """ + self.set_text(text[:10], 0xD2B5 + (index * PKMN_SIZE)) + + def get_player_monster_nickname(self, index): + """ + Returns player monster's nickname at a given index. + + Args: + index (int): Which monster (0-5). + """ + return self.get_text(0xD2B5 + (index * PKMN_SIZE)) + + def set_player_monster_move(self, index, move_index, move): + """ + Sets player monster's move at a given index. + + Args: + index (int): Which monster to change (0-5). + move_index (int): Which move to change (0-3). + move (int): Which type of move to set. + """ + self.pyboy.set_memory_value(0xD01C + (index * PKMN_SIZE) + move_index, move) + + def get_player_monster_move(self, index, move_index): + """ + Returns player monster's move at a given index. + + Args: + index (int): Which monster (0-5). + move_index (int): Which move to change (0-3). + """ + return self.pyboy.get_memory_value(0xD01C + (index * PKMN_SIZE) + move_index) + + def get_player_monster_current_hp(self, index): + """ + Returns player monster's current HP at a given index. + + Args: + index (int): Which monster (0-5). + """ + return self.get_int_at_address(0xD16C + (index * PKMN_SIZE)) + + def get_active_player_monster_current_hp(self): + return self.get_int_at_address(0xD015) + + def set_player_monster_current_hp(self, index, hp): + """ + Sets the current HP of a given player monster. + + Args: + index (int): Which monster to change (0-5). + hp (int): Health points. + """ + self.set_int_at_address(0xD16C + (index * PKMN_SIZE), hp) + + def set_active_player_monster_current_hp(self, hp): + self.set_int_at_address(0xD015, hp) + + def get_player_monster_max_hp(self, index): + """ + Returns player monster's max HP at a given index. + + Args: + index (int): Which monster (0-5). + """ + return self.get_int_at_address(0xD18D + (index * PKMN_SIZE)) + + def get_active_player_monster_max_hp(self): + return self.get_int_at_address(0xD023) + + def set_player_monster_max_hp(self, index, hp): + """ + Sets the max HP of a given player monster. + + Args: + index (int): Which monster to change (0-5). + hp (int): Health points. + """ + self.set_int_at_address(0xD18D + (index * PKMN_SIZE), hp) + + def set_active_player_monster_max_hp(self, hp): + return self.set_int_at_address(0xD023, hp) + + def set_player_monster_status(self, index, status): + """ + Sets the ailment status of a given player monster. + + Args: + index (int): Which monster to change (0-5). + status (int): Status to be set. + """ + assert status >= 0 and status < 0xFF + assert index < 6 + self.pyboy.set_memory_value(0xD16F + (index * PKMN_SIZE), status) + + def set_player_monster_asleep(self, index): + self.set_player_monster_status(index, constants.STATUS_ASLEEP) + + def set_player_monster_poisoned(self, index): + self.set_player_monster_status(index, constants.STATUS_POISONED) + + def set_player_monster_burned(self, index): + self.set_player_monster_status(index, constants.STATUS_BURNED) + + def set_player_monster_frozen(self, index): + self.set_player_monster_status(index, constants.STATUS_FROZEN) + + def set_player_monster_paralyzed(self, index): + self.set_player_monster_status(index, constants.STATUS_PARALYZED) + + def set_player_monster_no_ailment(self, index): + self.set_player_monster_status(index, 0) + + def get_player_money(self): + return self.get_int_at_address(0xD347, size=3) + + def set_active_player_monster_status(self, status): + self.pyboy.set_memory_value(0xD018, status) + + def set_active_player_monster_asleep(self): + self.set_active_player_monster_status(constants.STATUS_ASLEEP) + + def set_active_player_monster_poisoned(self): + self.set_active_player_monster_status(constants.STATUS_POISONED) + + def set_active_player_monster_burned(self): + self.set_active_player_monster_status(constants.STATUS_BURNED) + + def set_active_player_monster_frozen(self): + self.set_active_player_monster_status(constants.STATUS_FROZEN) + + def set_active_player_monster_paralyzed(self): + self.set_active_player_monster_status(constants.STATUS_PARALYZED) + + def set_active_player_monster_no_ailment(self): + self.set_active_player_monster_status(0) + + def set_active_player_monster_move(self, index, move): + self.pyboy.set_memory_value(0xD01C + index, move) + + def set_active_opponent_monster_move(self, index, move): + self.pyboy.set_memory_value(0xCFED + index, move) + + def set_active_player_monster_nickname(self, nickname): + self.set_text(nickname[:10], 0xD009) + + def set_active_opponent_monster_nickname(self, nickname): + self.set_text(nickname[:10], 0xCFDA) + + def set_active_opponent_monster_status(self, status): + self.pyboy.set_memory_value(0xCFE9, status) + + def set_active_opponent_monster_asleep(self): + self.set_active_opponent_monster_status(constants.STATUS_ASLEEP) + + def set_active_opponent_monster_poisoned(self): + self.set_active_opponent_monster_status(constants.STATUS_POISONED) + + def set_active_opponent_monster_burned(self): + self.set_active_opponent_monster_status(constants.STATUS_BURNED) + + def set_active_opponent_monster_frozen(self): + self.set_active_opponent_monster_status(constants.STATUS_FROZEN) + + def set_active_opponent_monster_paralyzed(self): + self.set_active_opponent_monster_status(constants.STATUS_PARALYZED) + + def set_active_opponent_monster_no_ailment(self): + self.set_active_opponent_monster_status(0) + + def heal_player_monster(self, index): + """ + Fully heals a player monster. + + Args: + index (int): Which monster to change (0-5). + """ + self.set_player_monster_no_ailment(index) + max_hp = self.get_player_monster_max_hp(index) + self.set_player_monster_current_hp(index, max_hp) + + def heal_active_player_monster(self): + self.set_active_player_monster_no_ailment() + max_hp = self.get_active_player_monster_max_hp() + self.set_active_player_monster_current_hp(max_hp) + + def is_battle_happening(self): + return self.pyboy.get_memory_value(0xD057) != 0 + + def get_current_map(self): + return self.pyboy.get_memory_value(0xD35E) + + def get_current_map_name(self): + return constants.MAP_NAMES[self.get_current_map()] + + def set_wild_encounter_rate(self, value): + self.pyboy.set_memory_value(0xD887, value) + + # TODO: Add player position functions From b6229b9db04dcdc9abd362d49f7d9cb9cbe17b16 Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Fri, 3 Nov 2023 19:26:14 -0400 Subject: [PATCH 03/74] Change files from Pokemon Red to PokemonGen1 as both games are functionally identical --- .../game_wrapper_pokemon_gen1/constants.py | 1399 +++++++++++++++++ .../game_wrapper_pokemon_gen1.pxd | 10 + .../game_wrapper_pokemon_gen1.py | 429 +++++ .../game_wrapper_pokemon_gen1/utils.py | 17 + pyboy/plugins/manager.pxd | 2 +- pyboy/plugins/manager.py | 2 +- 6 files changed, 1857 insertions(+), 2 deletions(-) create mode 100644 pyboy/plugins/game_wrapper_pokemon_gen1/constants.py create mode 100644 pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.pxd create mode 100644 pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py create mode 100644 pyboy/plugins/game_wrapper_pokemon_gen1/utils.py diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py b/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py new file mode 100644 index 000000000..4e857a32f --- /dev/null +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py @@ -0,0 +1,1399 @@ +STRING_TERMINATOR = 80 +ASCII_DELTA = 63 + +# Moves +MOVE_POUND = 0x01 +MOVE_KARATE_CHOP = 0x02 +MOVE_DOUBLESLAP = 0x03 +MOVE_COMET_PUNCH = 0x04 +MOVE_MEGA_PUNCH = 0x05 +MOVE_PAY_DAY = 0x06 +MOVE_FIRE_PUNCH = 0x07 +MOVE_ICE_PUNCH = 0x08 +MOVE_THUNDERPUNCH = 0x09 +MOVE_SCRATCH = 0x0a +MOVE_VICEGRIP = 0x0b +MOVE_GUILLOTINE = 0x0c +MOVE_RAZOR_WIND = 0x0d +MOVE_SWORDS_DANCE = 0x0e +MOVE_CUT = 0x0f +MOVE_GUST = 0x10 +MOVE_WING_ATTACK = 0x11 +MOVE_WHIRLWIND = 0x12 +MOVE_FLY = 0x13 +MOVE_BIND = 0x14 +MOVE_SLAM = 0x15 +MOVE_VINE_WHIP = 0x16 +MOVE_STOMP = 0x17 +MOVE_DOUBLE_KICK = 0x18 +MOVE_MEGA_KICK = 0x19 +MOVE_JUMP_KICK = 0x1a +MOVE_ROLLING_KICK = 0x1b +MOVE_SAND_ATTACK = 0x1c +MOVE_HEADBUTT = 0x1d +MOVE_HORN_ATTACK = 0x1e +MOVE_FURY_ATTACK = 0x1f +MOVE_HORN_DRILL = 0x20 +MOVE_TACKLE = 0x21 +MOVE_BODY_SLAM = 0x22 +MOVE_WRAP = 0x23 +MOVE_TAKE_DOWN = 0x24 +MOVE_THRASH = 0x25 +MOVE_DOUBLE_EDGE = 0x26 +MOVE_TAIL_WHIP = 0x27 +MOVE_POISON_STING = 0x28 +MOVE_TWINEEDLE = 0x29 +MOVE_PIN_MISSILE = 0x2a +MOVE_LEER = 0x2b +MOVE_BITE = 0x2c +MOVE_GROWL = 0x2d +MOVE_ROAR = 0x2e +MOVE_SING = 0x2f +MOVE_SUPERSONIC = 0x30 +MOVE_SONICBOOM = 0x31 +MOVE_DISABLE = 0x32 +MOVE_ACID = 0x33 +MOVE_EMBER = 0x34 +MOVE_FLAMETHROWER = 0x35 +MOVE_MIST = 0x36 +MOVE_WATER_GUN = 0x37 +MOVE_HYDRO_PUMP = 0x38 +MOVE_SURF = 0x39 +MOVE_ICE_BEAM = 0x3a +MOVE_BLIZZARD = 0x3b +MOVE_PSYBEAM = 0x3c +MOVE_BUBBLEBEAM = 0x3d +MOVE_AURORA_BEAM = 0x3e +MOVE_HYPER_BEAM = 0x3f +MOVE_PECK = 0x40 +MOVE_DRILL_PECK = 0x41 +MOVE_SUBMISSION = 0x42 +MOVE_LOW_KICK = 0x43 +MOVE_COUNTER = 0x44 +MOVE_SEISMIC_TOSS = 0x45 +MOVE_STRENGTH = 0x46 +MOVE_ABSORB = 0x47 +MOVE_MEGA_DRAIN = 0x48 +MOVE_LEECH_SEED = 0x49 +MOVE_GROWTH = 0x4a +MOVE_RAZOR_LEAF = 0x4b +MOVE_SOLARBEAM = 0x4c +MOVE_POISONPOWDER = 0x4d +MOVE_STUN_SPORE = 0x4e +MOVE_SLEEP_POWDER = 0x4f +MOVE_PETAL_DANCE = 0x50 +MOVE_STRING_SHOT = 0x51 +MOVE_DRAGON_RAGE = 0x52 +MOVE_FIRE_SPIN = 0x53 +MOVE_THUNDERSHOCK = 0x54 +MOVE_THUNDERBOLT = 0x55 +MOVE_THUNDER_WAVE = 0x56 +MOVE_THUNDER = 0x57 +MOVE_ROCK_THROW = 0x58 +MOVE_EARTHQUAKE = 0x59 +MOVE_FISSURE = 0x5a +MOVE_DIG = 0x5b +MOVE_TOXIC = 0x5c +MOVE_CONFUSION = 0x5d +MOVE_PSYCHIC_M = 0x5e +MOVE_HYPNOSIS = 0x5f +MOVE_MEDITATE = 0x60 +MOVE_AGILITY = 0x61 +MOVE_QUICK_ATTACK = 0x62 +MOVE_RAGE = 0x63 +MOVE_TELEPORT = 0x64 +MOVE_NIGHT_SHADE = 0x65 +MOVE_MIMIC = 0x66 +MOVE_SCREECH = 0x67 +MOVE_DOUBLE_TEAM = 0x68 +MOVE_RECOVER = 0x69 +MOVE_HARDEN = 0x6a +MOVE_MINIMIZE = 0x6b +MOVE_SMOKESCREEN = 0x6c +MOVE_CONFUSE_RAY = 0x6d +MOVE_WITHDRAW = 0x6e +MOVE_DEFENSE_CURL = 0x6f +MOVE_BARRIER = 0x70 +MOVE_LIGHT_SCREEN = 0x71 +MOVE_HAZE = 0x72 +MOVE_REFLECT = 0x73 +MOVE_FOCUS_ENERGY = 0x74 +MOVE_BIDE = 0x75 +MOVE_METRONOME = 0x76 +MOVE_MIRROR_MOVE = 0x77 +MOVE_SELFDESTRUCT = 0x78 +MOVE_EGG_BOMB = 0x79 +MOVE_LICK = 0x7a +MOVE_SMOG = 0x7b +MOVE_SLUDGE = 0x7c +MOVE_BONE_CLUB = 0x7d +MOVE_FIRE_BLAST = 0x7e +MOVE_WATERFALL = 0x7f +MOVE_CLAMP = 0x80 +MOVE_SWIFT = 0x81 +MOVE_SKULL_BASH = 0x82 +MOVE_SPIKE_CANNON = 0x83 +MOVE_CONSTRICT = 0x84 +MOVE_AMNESIA = 0x85 +MOVE_KINESIS = 0x86 +MOVE_SOFTBOILED = 0x87 +MOVE_HI_JUMP_KICK = 0x88 +MOVE_GLARE = 0x89 +MOVE_DREAM_EATER = 0x8a +MOVE_POISON_GAS = 0x8b +MOVE_BARRAGE = 0x8c +MOVE_LEECH_LIFE = 0x8d +MOVE_LOVELY_KISS = 0x8e +MOVE_SKY_ATTACK = 0x8f +MOVE_TRANSFORM = 0x90 +MOVE_BUBBLE = 0x91 +MOVE_DIZZY_PUNCH = 0x92 +MOVE_SPORE = 0x93 +MOVE_FLASH = 0x94 +MOVE_PSYWAVE = 0x95 +MOVE_SPLASH = 0x96 +MOVE_ACID_ARMOR = 0x97 +MOVE_CRABHAMMER = 0x98 +MOVE_EXPLOSION = 0x99 +MOVE_FURY_SWIPES = 0x9a +MOVE_BONEMERANG = 0x9b +MOVE_REST = 0x9c +MOVE_ROCK_SLIDE = 0x9d +MOVE_HYPER_FANG = 0x9e +MOVE_SHARPEN = 0x9f +MOVE_CONVERSION = 0xa0 +MOVE_TRI_ATTACK = 0xa1 +MOVE_SUPER_FANG = 0xa2 +MOVE_SLASH = 0xa3 +MOVE_SUBSTITUTE = 0xa4 + +MONSTER_RHYDON = 0x01 +MONSTER_KANGASKHAN = 0x02 +MONSTER_NIDORAN_M = 0x03 +MONSTER_CLEFAIRY = 0x04 +MONSTER_SPEAROW = 0x05 +MONSTER_VOLTORB = 0x06 +MONSTER_NIDOKING = 0x07 +MONSTER_SLOWBRO = 0x08 +MONSTER_IVYSAUR = 0x09 +MONSTER_EXEGGUTOR = 0x0A +MONSTER_LICKITUNG = 0x0B +MONSTER_EXEGGCUTE = 0x0C +MONSTER_GRIMER = 0x0D +MONSTER_GENGAR = 0x0E +MONSTER_NIDORAN_F = 0x0F +MONSTER_NIDOQUEEN = 0x10 +MONSTER_CUBONE = 0x11 +MONSTER_RHYHORN = 0x12 +MONSTER_LAPRAS = 0x13 +MONSTER_ARCANINE = 0x14 +MONSTER_MEW = 0x15 +MONSTER_GYARADOS = 0x16 +MONSTER_SHELLDER = 0x17 +MONSTER_TENTACOOL = 0x18 +MONSTER_GASTLY = 0x19 +MONSTER_SCYTHER = 0x1A +MONSTER_STARYU = 0x1B +MONSTER_BLASTOISE = 0x1C +MONSTER_PINSIR = 0x1D +MONSTER_TANGELA = 0x1E +MONSTER_MISSINGNO_1F = 0x1F +MONSTER_MISSINGNO_20 = 0x20 +MONSTER_GROWLITHE = 0x21 +MONSTER_ONIX = 0x22 +MONSTER_FEAROW = 0x23 +MONSTER_PIDGEY = 0x24 +MONSTER_SLOWPOKE = 0x25 +MONSTER_KADABRA = 0x26 +MONSTER_GRAVELER = 0x27 +MONSTER_CHANSEY = 0x28 +MONSTER_MACHOKE = 0x29 +MONSTER_MR_MIME = 0x2A +MONSTER_HITMONLEE = 0x2B +MONSTER_HITMONCHAN = 0x2C +MONSTER_ARBOK = 0x2D +MONSTER_PARASECT = 0x2E +MONSTER_PSYDUCK = 0x2F +MONSTER_DROWZEE = 0x30 +MONSTER_GOLEM = 0x31 +MONSTER_MISSINGNO_32 = 0x32 +MONSTER_MAGMAR = 0x33 +MONSTER_MISSINGNO_34 = 0x34 +MONSTER_ELECTABUZZ = 0x35 +MONSTER_MAGNETON = 0x36 +MONSTER_KOFFING = 0x37 +MONSTER_MISSINGNO_38 = 0x38 +MONSTER_MANKEY = 0x39 +MONSTER_SEEL = 0x3A +MONSTER_DIGLETT = 0x3B +MONSTER_TAUROS = 0x3C +MONSTER_MISSINGNO_3D = 0x3D +MONSTER_MISSINGNO_3E = 0x3E +MONSTER_MISSINGNO_3F = 0x3F +MONSTER_FARFETCHD = 0x40 +MONSTER_VENONAT = 0x41 +MONSTER_DRAGONITE = 0x42 +MONSTER_MISSINGNO_43 = 0x43 +MONSTER_MISSINGNO_44 = 0x44 +MONSTER_MISSINGNO_45 = 0x45 +MONSTER_DODUO = 0x46 +MONSTER_POLIWAG = 0x47 +MONSTER_JYNX = 0x48 +MONSTER_MOLTRES = 0x49 +MONSTER_ARTICUNO = 0x4A +MONSTER_ZAPDOS = 0x4B +MONSTER_DITTO = 0x4C +MONSTER_MEOWTH = 0x4D +MONSTER_KRABBY = 0x4E +MONSTER_MISSINGNO_4F = 0x4F +MONSTER_MISSINGNO_50 = 0x50 +MONSTER_MISSINGNO_51 = 0x51 +MONSTER_VULPIX = 0x52 +MONSTER_NINETALES = 0x53 +MONSTER_PIKACHU = 0x54 +MONSTER_RAICHU = 0x55 +MONSTER_MISSINGNO_56 = 0x56 +MONSTER_MISSINGNO_57 = 0x57 +MONSTER_DRATINI = 0x58 +MONSTER_DRAGONAIR = 0x59 +MONSTER_KABUTO = 0x5A +MONSTER_KABUTOPS = 0x5B +MONSTER_HORSEA = 0x5C +MONSTER_SEADRA = 0x5D +MONSTER_MISSINGNO_5E = 0x5E +MONSTER_MISSINGNO_5F = 0x5F +MONSTER_SANDSHREW = 0x60 +MONSTER_SANDSLASH = 0x61 +MONSTER_OMANYTE = 0x62 +MONSTER_OMASTAR = 0x63 +MONSTER_JIGGLYPUFF = 0x64 +MONSTER_WIGGLYTUFF = 0x65 +MONSTER_EEVEE = 0x66 +MONSTER_FLAREON = 0x67 +MONSTER_JOLTEON = 0x68 +MONSTER_VAPOREON = 0x69 +MONSTER_MACHOP = 0x6A +MONSTER_ZUBAT = 0x6B +MONSTER_EKANS = 0x6C +MONSTER_PARAS = 0x6D +MONSTER_POLIWHIRL = 0x6E +MONSTER_POLIWRATH = 0x6F +MONSTER_WEEDLE = 0x70 +MONSTER_KAKUNA = 0x71 +MONSTER_BEEDRILL = 0x72 +MONSTER_MISSINGNO_73 = 0x73 +MONSTER_DODRIO = 0x74 +MONSTER_PRIMEAPE = 0x75 +MONSTER_DUGTRIO = 0x76 +MONSTER_VENOMOTH = 0x77 +MONSTER_DEWGONG = 0x78 +MONSTER_MISSINGNO_79 = 0x79 +MONSTER_MISSINGNO_7A = 0x7A +MONSTER_CATERPIE = 0x7B +MONSTER_METAPOD = 0x7C +MONSTER_BUTTERFREE = 0x7D +MONSTER_MACHAMP = 0x7E +MONSTER_MISSINGNO_7F = 0x7F +MONSTER_GOLDUCK = 0x80 +MONSTER_HYPNO = 0x81 +MONSTER_GOLBAT = 0x82 +MONSTER_MEWTWO = 0x83 +MONSTER_SNORLAX = 0x84 +MONSTER_MAGIKARP = 0x85 +MONSTER_MISSINGNO_86 = 0x86 +MONSTER_MISSINGNO_87 = 0x87 +MONSTER_MUK = 0x88 +MONSTER_MISSINGNO_89 = 0x89 +MONSTER_KINGLER = 0x8A +MONSTER_CLOYSTER = 0x8B +MONSTER_MISSINGNO_8C = 0x8C +MONSTER_ELECTRODE = 0x8D +MONSTER_CLEFABLE = 0x8E +MONSTER_WEEZING = 0x8F +MONSTER_PERSIAN = 0x90 +MONSTER_MAROWAK = 0x91 +MONSTER_MISSINGNO_92 = 0x92 +MONSTER_HAUNTER = 0x93 +MONSTER_ABRA = 0x94 +MONSTER_ALAKAZAM = 0x95 +MONSTER_PIDGEOTTO = 0x96 +MONSTER_PIDGEOT = 0x97 +MONSTER_STARMIE = 0x98 +MONSTER_BULBASAUR = 0x99 +MONSTER_VENUSAUR = 0x9A +MONSTER_TENTACRUEL = 0x9B +MONSTER_MISSINGNO_9C = 0x9C +MONSTER_GOLDEEN = 0x9D +MONSTER_SEAKING = 0x9E +MONSTER_MISSINGNO_9F = 0x9F +MONSTER_MISSINGNO_A0 = 0xA0 +MONSTER_MISSINGNO_A1 = 0xA1 +MONSTER_MISSINGNO_A2 = 0xA2 +MONSTER_PONYTA = 0xA3 +MONSTER_RAPIDASH = 0xA4 +MONSTER_RATTATA = 0xA5 +MONSTER_RATICATE = 0xA6 +MONSTER_NIDORINO = 0xA7 +MONSTER_NIDORINA = 0xA8 +MONSTER_GEODUDE = 0xA9 +MONSTER_PORYGON = 0xAA +MONSTER_AERODACTYL = 0xAB +MONSTER_MISSINGNO_AC = 0xAC +MONSTER_MAGNEMITE = 0xAD +MONSTER_MISSINGNO_AE = 0xAE +MONSTER_MISSINGNO_AF = 0xAF +MONSTER_CHARMANDER = 0xB0 +MONSTER_SQUIRTLE = 0xB1 +MONSTER_CHARMELEON = 0xB2 +MONSTER_WARTORTLE = 0xB3 +MONSTER_CHARIZARD = 0xB4 +MONSTER_MISSINGNO_B5 = 0xB5 +MONSTER_FOSSIL_KABUTOPS = 0xB6 +MONSTER_FOSSIL_AERODACTYL = 0xB7 +MONSTER_MON_GHOST = 0xB8 +MONSTER_ODDISH = 0xB9 +MONSTER_GLOOM = 0xBA +MONSTER_VILEPLUME = 0xBB +MONSTER_BELLSPROUT = 0xBC +MONSTER_WEEPINBELL = 0xBD +MONSTER_VICTREEBEL = 0xBE + +ITEM_MASTER_BALL = 0x01 +ITEM_ULTRA_BALL = 0x02 +ITEM_GREAT_BALL = 0x03 +ITEM_POKE_BALL = 0x04 +ITEM_TOWN_MAP = 0x05 +ITEM_BICYCLE = 0x06 +ITEM_SURFBOARD = 0x07 +ITEM_SAFARI_BALL = 0x08 +ITEM_POKEDEX = 0x09 +ITEM_MOON_STONE = 0x0A +ITEM_ANTIDOTE = 0x0B +ITEM_BURN_HEAL = 0x0C +ITEM_ICE_HEAL = 0x0D +ITEM_AWAKENING = 0x0E +ITEM_PARLYZ_HEAL = 0x0F +ITEM_FULL_RESTORE = 0x10 +ITEM_MAX_POTION = 0x11 +ITEM_HYPER_POTION = 0x12 +ITEM_SUPER_POTION = 0x13 +ITEM_POTION = 0x14 +ITEM_BOULDERBADGE = 0x15 +ITEM_CASCADEBADGE = 0x16 +ITEM_THUNDERBADGE = 0x17 +ITEM_RAINBOWBADGE = 0x18 +ITEM_SOULBADGE = 0x19 +ITEM_MARSHBADGE = 0x1A +ITEM_VOLCANOBADGE = 0x1B +ITEM_EARTHBADGE = 0x1C +ITEM_ESCAPE_ROPE = 0x1D +ITEM_REPEL = 0x1E +ITEM_OLD_AMBER = 0x1F +ITEM_FIRE_STONE = 0x20 +ITEM_THUNDER_STONE = 0x21 +ITEM_WATER_STONE = 0x22 +ITEM_HP_UP = 0x23 +ITEM_PROTEIN = 0x24 +ITEM_IRON = 0x25 +ITEM_CARBOS = 0x26 +ITEM_CALCIUM = 0x27 +ITEM_RARE_CANDY = 0x28 +ITEM_DOME_FOSSIL = 0x29 +ITEM_HELIX_FOSSIL = 0x2A +ITEM_SECRET_KEY = 0x2B +ITEM_UNUSED_ITEM = 0x2C +ITEM_BIKE_VOUCHER = 0x2D +ITEM_X_ACCURACY = 0x2E +ITEM_LEAF_STONE = 0x2F +ITEM_CARD_KEY = 0x30 +ITEM_NUGGET = 0x31 +ITEM_PP_UP_2 = 0x32 +ITEM_POKE_DOLL = 0x33 +ITEM_FULL_HEAL = 0x34 +ITEM_REVIVE = 0x35 +ITEM_MAX_REVIVE = 0x36 +ITEM_GUARD_SPEC = 0x37 +ITEM_SUPER_REPEL = 0x38 +ITEM_MAX_REPEL = 0x39 +ITEM_DIRE_HIT = 0x3A +ITEM_COIN = 0x3B +ITEM_FRESH_WATER = 0x3C +ITEM_SODA_POP = 0x3D +ITEM_LEMONADE = 0x3E +ITEM_S_S_TICKET = 0x3F +ITEM_GOLD_TEETH = 0x40 +ITEM_X_ATTACK = 0x41 +ITEM_X_DEFEND = 0x42 +ITEM_X_SPEED = 0x43 +ITEM_X_SPECIAL = 0x44 +ITEM_COIN_CASE = 0x45 +ITEM_OAKS_PARCEL = 0x46 +ITEM_ITEMFINDER = 0x47 +ITEM_SILPH_SCOPE = 0x48 +ITEM_POKE_FLUTE = 0x49 +ITEM_LIFT_KEY = 0x4A +ITEM_EXP_ALL = 0x4B +ITEM_OLD_ROD = 0x4C +ITEM_GOOD_ROD = 0x4D +ITEM_SUPER_ROD = 0x4E +ITEM_PP_UP = 0x4F +ITEM_ETHER = 0x50 +ITEM_MAX_ETHER = 0x51 +ITEM_ELIXER = 0x52 +ITEM_MAX_ELIXER = 0x53 +ITEM_FLOOR_B2F = 0x54 +ITEM_FLOOR_B1F = 0x55 +ITEM_FLOOR_1F = 0x56 +ITEM_FLOOR_2F = 0x57 +ITEM_FLOOR_3F = 0x58 +ITEM_FLOOR_4F = 0x59 +ITEM_FLOOR_5F = 0x5A +ITEM_FLOOR_6F = 0x5B +ITEM_FLOOR_7F = 0x5C +ITEM_FLOOR_8F = 0x5D +ITEM_FLOOR_9F = 0x5E +ITEM_FLOOR_10F = 0x5F +ITEM_FLOOR_11F = 0x60 +ITEM_FLOOR_B4F = 0x61 +ITEM_HM_01 = 0xC4 +ITEM_HM_02 = 0xC5 +ITEM_HM_03 = 0xC6 +ITEM_HM_04 = 0xC7 +ITEM_HM_05 = 0xC8 +ITEM_TM_01 = 0xC9 +ITEM_TM_02 = 0xCA +ITEM_TM_03 = 0xCB +ITEM_TM_04 = 0xCC +ITEM_TM_05 = 0xCD +ITEM_TM_06 = 0xCE +ITEM_TM_07 = 0xCF +ITEM_TM_08 = 0xD0 +ITEM_TM_09 = 0xD1 +ITEM_TM_10 = 0xD2 +ITEM_TM_11 = 0xD3 +ITEM_TM_12 = 0xD4 +ITEM_TM_13 = 0xD5 +ITEM_TM_14 = 0xD6 +ITEM_TM_15 = 0xD7 +ITEM_TM_16 = 0xD8 +ITEM_TM_17 = 0xD9 +ITEM_TM_18 = 0xDA +ITEM_TM_19 = 0xDB +ITEM_TM_20 = 0xDC +ITEM_TM_21 = 0xDD +ITEM_TM_22 = 0xDE +ITEM_TM_23 = 0xDF +ITEM_TM_24 = 0xE0 +ITEM_TM_25 = 0xE1 +ITEM_TM_26 = 0xE2 +ITEM_TM_27 = 0xE3 +ITEM_TM_28 = 0xE4 +ITEM_TM_29 = 0xE5 +ITEM_TM_30 = 0xE6 +ITEM_TM_31 = 0xE7 +ITEM_TM_32 = 0xE8 +ITEM_TM_33 = 0xE9 +ITEM_TM_34 = 0xEA +ITEM_TM_35 = 0xEB +ITEM_TM_36 = 0xEC +ITEM_TM_37 = 0xED +ITEM_TM_38 = 0xEE +ITEM_TM_39 = 0xEF +ITEM_TM_40 = 0xF0 +ITEM_TM_41 = 0xF1 +ITEM_TM_42 = 0xF2 +ITEM_TM_43 = 0xF3 +ITEM_TM_44 = 0xF4 +ITEM_TM_45 = 0xF5 +ITEM_TM_46 = 0xF6 +ITEM_TM_47 = 0xF7 +ITEM_TM_48 = 0xF8 +ITEM_TM_49 = 0xF9 +ITEM_TM_50 = 0xFA + +SPRITE_RED = 0x01 +SPRITE_BLUE = 0x02 +SPRITE_OAK = 0x03 +SPRITE_BUG_CATCHER = 0x04 +SPRITE_SLOWBRO = 0x05 +SPRITE_LASS = 0x06 +SPRITE_BLACK_HAIR_BOY_1 = 0x07 +SPRITE_LITTLE_GIRL = 0x08 +SPRITE_BIRD = 0x09 +SPRITE_FAT_BALD_GUY = 0x0a +SPRITE_GAMBLER = 0x0b +SPRITE_BLACK_HAIR_BOY_2 = 0x0c +SPRITE_GIRL = 0x0d +SPRITE_HIKER = 0x0e +SPRITE_FOULARD_WOMAN = 0x0f +SPRITE_GENTLEMAN = 0x10 +SPRITE_DAISY = 0x11 +SPRITE_BIKER = 0x12 +SPRITE_SAILOR = 0x13 +SPRITE_COOK = 0x14 +SPRITE_BIKE_SHOP_GUY = 0x15 +SPRITE_MR_FUJI = 0x16 +SPRITE_GIOVANNI = 0x17 +SPRITE_ROCKET = 0x18 +SPRITE_MEDIUM = 0x19 +SPRITE_WAITER = 0x1a +SPRITE_ERIKA = 0x1b +SPRITE_MOM_GEISHA = 0x1c +SPRITE_BRUNETTE_GIRL = 0x1d +SPRITE_LANCE = 0x1e +SPRITE_OAK_SCIENTIST_AIDE = 0x1f +SPRITE_OAK_AIDE = 0x20 +SPRITE_ROCKER = 0x21 +SPRITE_SWIMMER = 0x22 +SPRITE_WHITE_PLAYER = 0x23 +SPRITE_GYM_HELPER = 0x24 +SPRITE_OLD_PERSON = 0x25 +SPRITE_MART_GUY = 0x26 +SPRITE_FISHER = 0x27 +SPRITE_OLD_MEDIUM_WOMAN = 0x28 +SPRITE_NURSE = 0x29 +SPRITE_CABLE_CLUB_WOMAN = 0x2a +SPRITE_MR_MASTERBALL = 0x2b +SPRITE_LAPRAS_GIVER = 0x2c +SPRITE_WARDEN = 0x2d +SPRITE_SS_CAPTAIN = 0x2e +SPRITE_FISHER2 = 0x2f +SPRITE_BLACKBELT = 0x30 +SPRITE_GUARD = 0x31 +SPRITE_COP_GUARD = 0x32 +SPRITE_MOM = 0x33 +SPRITE_BALDING_GUY = 0x34 +SPRITE_YOUNG_BOY = 0x35 +SPRITE_GAMEBOY_KID = 0x36 +SPRITE_GAMEBOY_KID_COPY = 0x37 +SPRITE_CLEFAIRY = 0x38 +SPRITE_AGATHA = 0x39 +SPRITE_BRUNO = 0x3a +SPRITE_LORELEI = 0x3b +SPRITE_SEEL = 0x3c +SPRITE_BALL = 0x3d +SPRITE_OMANYTE = 0x3e +SPRITE_BOULDER = 0x3f +SPRITE_PAPER_SHEET = 0x40 +SPRITE_BOOK_MAP_DEX = 0x41 +SPRITE_CLIPBOARD = 0x42 +SPRITE_SNORLAX = 0x43 +SPRITE_OLD_AMBER_COPY = 0x44 +SPRITE_OLD_AMBER = 0x45 +SPRITE_LYING_OLD_MAN_UNUSED_1 = 0x46 +SPRITE_LYING_OLD_MAN_UNUSED_2 = 0x47 +SPRITE_LYING_OLD_MAN = 0x48 + +MAP_PALLET_TOWN = 0x00 +MAP_VIRIDIAN_CITY = 0x01 +MAP_PEWTER_CITY = 0x02 +MAP_CERULEAN_CITY = 0x03 +MAP_LAVENDER_TOWN = 0x04 +MAP_VERMILION_CITY = 0x05 +MAP_CELADON_CITY = 0x06 +MAP_FUCHSIA_CITY = 0x07 +MAP_CINNABAR_ISLAND = 0x08 +MAP_INDIGO_PLATEAU = 0x09 +MAP_SAFFRON_CITY = 0x0A +MAP_UNUSED_MAP_0B = 0x0B +MAP_ROUTE_1 = 0x0C +MAP_ROUTE_2 = 0x0D +MAP_ROUTE_3 = 0x0E +MAP_ROUTE_4 = 0x0F +MAP_ROUTE_5 = 0x10 +MAP_ROUTE_6 = 0x11 +MAP_ROUTE_7 = 0x12 +MAP_ROUTE_8 = 0x13 +MAP_ROUTE_9 = 0x14 +MAP_ROUTE_10 = 0x15 +MAP_ROUTE_11 = 0x16 +MAP_ROUTE_12 = 0x17 +MAP_ROUTE_13 = 0x18 +MAP_ROUTE_14 = 0x19 +MAP_ROUTE_15 = 0x1A +MAP_ROUTE_16 = 0x1B +MAP_ROUTE_17 = 0x1C +MAP_ROUTE_18 = 0x1D +MAP_ROUTE_19 = 0x1E +MAP_ROUTE_20 = 0x1F +MAP_ROUTE_21 = 0x20 +MAP_ROUTE_22 = 0x21 +MAP_ROUTE_23 = 0x22 +MAP_ROUTE_24 = 0x23 +MAP_ROUTE_25 = 0x24 +MAP_REDS_HOUSE_1F = 0x25 +MAP_REDS_HOUSE_2F = 0x26 +MAP_BLUES_HOUSE = 0x27 +MAP_OAKS_LAB = 0x28 +MAP_VIRIDIAN_POKECENTER = 0x29 +MAP_VIRIDIAN_MART = 0x2A +MAP_VIRIDIAN_SCHOOL_HOUSE = 0x2B +MAP_VIRIDIAN_NICKNAME_HOUSE = 0x2C +MAP_VIRIDIAN_GYM = 0x2D +MAP_DIGLETTS_CAVE_ROUTE_2 = 0x2E +MAP_VIRIDIAN_FOREST_NORTH_GATE = 0x2F +MAP_ROUTE_2_TRADE_HOUSE = 0x30 +MAP_ROUTE_2_GATE = 0x31 +MAP_VIRIDIAN_FOREST_SOUTH_GATE = 0x32 +MAP_VIRIDIAN_FOREST = 0x33 +MAP_MUSEUM_1F = 0x34 +MAP_MUSEUM_2F = 0x35 +MAP_PEWTER_GYM = 0x36 +MAP_PEWTER_NIDORAN_HOUSE = 0x37 +MAP_PEWTER_MART = 0x38 +MAP_PEWTER_SPEECH_HOUSE = 0x39 +MAP_PEWTER_POKECENTER = 0x3A +MAP_MT_MOON_1F = 0x3B +MAP_MT_MOON_B1F = 0x3C +MAP_MT_MOON_B2F = 0x3D +MAP_CERULEAN_TRASHED_HOUSE = 0x3E +MAP_CERULEAN_TRADE_HOUSE = 0x3F +MAP_CERULEAN_POKECENTER = 0x40 +MAP_CERULEAN_GYM = 0x41 +MAP_BIKE_SHOP = 0x42 +MAP_CERULEAN_MART = 0x43 +MAP_MT_MOON_POKECENTER = 0x44 +MAP_CERULEAN_TRASHED_HOUSE_COPY = 0x45 +MAP_ROUTE_5_GATE = 0x46 +MAP_UNDERGROUND_PATH_ROUTE_5 = 0x47 +MAP_DAYCARE = 0x48 +MAP_ROUTE_6_GATE = 0x49 +MAP_UNDERGROUND_PATH_ROUTE_6 = 0x4A +MAP_UNDERGROUND_PATH_ROUTE_6_COPY = 0x4B +MAP_ROUTE_7_GATE = 0x4C +MAP_UNDERGROUND_PATH_ROUTE_7 = 0x4D +MAP_UNDERGROUND_PATH_ROUTE_7_COPY = 0x4E +MAP_ROUTE_8_GATE = 0x4F +MAP_UNDERGROUND_PATH_ROUTE_8 = 0x50 +MAP_ROCK_TUNNEL_POKECENTER = 0x51 +MAP_ROCK_TUNNEL_1F = 0x52 +MAP_POWER_PLANT = 0x53 +MAP_ROUTE_11_GATE_1F = 0x54 +MAP_DIGLETTS_CAVE_ROUTE_11 = 0x55 +MAP_ROUTE_11_GATE_2F = 0x56 +MAP_ROUTE_12_GATE_1F = 0x57 +MAP_BILLS_HOUSE = 0x58 +MAP_VERMILION_POKECENTER = 0x59 +MAP_POKEMON_FAN_CLUB = 0x5A +MAP_VERMILION_MART = 0x5B +MAP_VERMILION_GYM = 0x5C +MAP_VERMILION_PIDGEY_HOUSE = 0x5D +MAP_VERMILION_DOCK = 0x5E +MAP_SS_ANNE_1F = 0x5F +MAP_SS_ANNE_2F = 0x60 +MAP_SS_ANNE_3F = 0x61 +MAP_SS_ANNE_B1F = 0x62 +MAP_SS_ANNE_BOW = 0x63 +MAP_SS_ANNE_KITCHEN = 0x64 +MAP_SS_ANNE_CAPTAINS_ROOM = 0x65 +MAP_SS_ANNE_1F_ROOMS = 0x66 +MAP_SS_ANNE_2F_ROOMS = 0x67 +MAP_SS_ANNE_B1F_ROOMS = 0x68 +MAP_UNUSED_MAP_69 = 0x69 +MAP_UNUSED_MAP_6A = 0x6A +MAP_UNUSED_MAP_6B = 0x6B +MAP_VICTORY_ROAD_1F = 0x6C +MAP_UNUSED_MAP_6D = 0x6D +MAP_UNUSED_MAP_6E = 0x6E +MAP_UNUSED_MAP_6F = 0x6F +MAP_UNUSED_MAP_70 = 0x70 +MAP_LANCES_ROOM = 0x71 +MAP_UNUSED_MAP_72 = 0x72 +MAP_UNUSED_MAP_73 = 0x73 +MAP_UNUSED_MAP_74 = 0x74 +MAP_UNUSED_MAP_75 = 0x75 +MAP_HALL_OF_FAME = 0x76 +MAP_UNDERGROUND_PATH_NORTH_SOUTH = 0x77 +MAP_CHAMPIONS_ROOM = 0x78 +MAP_UNDERGROUND_PATH_WEST_EAST = 0x79 +MAP_CELADON_MART_1F = 0x7A +MAP_CELADON_MART_2F = 0x7B +MAP_CELADON_MART_3F = 0x7C +MAP_CELADON_MART_4F = 0x7D +MAP_CELADON_MART_ROOF = 0x7E +MAP_CELADON_MART_ELEVATOR = 0x7F +MAP_CELADON_MANSION_1F = 0x80 +MAP_CELADON_MANSION_2F = 0x81 +MAP_CELADON_MANSION_3F = 0x82 +MAP_CELADON_MANSION_ROOF = 0x83 +MAP_CELADON_MANSION_ROOF_HOUSE = 0x84 +MAP_CELADON_POKECENTER = 0x85 +MAP_CELADON_GYM = 0x86 +MAP_GAME_CORNER = 0x87 +MAP_CELADON_MART_5F = 0x88 +MAP_GAME_CORNER_PRIZE_ROOM = 0x89 +MAP_CELADON_DINER = 0x8A +MAP_CELADON_CHIEF_HOUSE = 0x8B +MAP_CELADON_HOTEL = 0x8C +MAP_LAVENDER_POKECENTER = 0x8D +MAP_POKEMON_TOWER_1F = 0x8E +MAP_POKEMON_TOWER_2F = 0x8F +MAP_POKEMON_TOWER_3F = 0x90 +MAP_POKEMON_TOWER_4F = 0x91 +MAP_POKEMON_TOWER_5F = 0x92 +MAP_POKEMON_TOWER_6F = 0x93 +MAP_POKEMON_TOWER_7F = 0x94 +MAP_MR_FUJIS_HOUSE = 0x95 +MAP_LAVENDER_MART = 0x96 +MAP_LAVENDER_CUBONE_HOUSE = 0x97 +MAP_FUCHSIA_MART = 0x98 +MAP_FUCHSIA_BILLS_GRANDPAS_HOUSE = 0x99 +MAP_FUCHSIA_POKECENTER = 0x9A +MAP_WARDENS_HOUSE = 0x9B +MAP_SAFARI_ZONE_GATE = 0x9C +MAP_FUCHSIA_GYM = 0x9D +MAP_FUCHSIA_MEETING_ROOM = 0x9E +MAP_SEAFOAM_ISLANDS_B1F = 0x9F +MAP_SEAFOAM_ISLANDS_B2F = 0xA0 +MAP_SEAFOAM_ISLANDS_B3F = 0xA1 +MAP_SEAFOAM_ISLANDS_B4F = 0xA2 +MAP_VERMILION_OLD_ROD_HOUSE = 0xA3 +MAP_FUCHSIA_GOOD_ROD_HOUSE = 0xA4 +MAP_POKEMON_MANSION_1F = 0xA5 +MAP_CINNABAR_GYM = 0xA6 +MAP_CINNABAR_LAB = 0xA7 +MAP_CINNABAR_LAB_TRADE_ROOM = 0xA8 +MAP_CINNABAR_LAB_METRONOME_ROOM = 0xA9 +MAP_CINNABAR_LAB_FOSSIL_ROOM = 0xAA +MAP_CINNABAR_POKECENTER = 0xAB +MAP_CINNABAR_MART = 0xAC +MAP_CINNABAR_MART_COPY = 0xAD +MAP_INDIGO_PLATEAU_LOBBY = 0xAE +MAP_COPYCATS_HOUSE_1F = 0xAF +MAP_COPYCATS_HOUSE_2F = 0xB0 +MAP_FIGHTING_DOJO = 0xB1 +MAP_SAFFRON_GYM = 0xB2 +MAP_SAFFRON_PIDGEY_HOUSE = 0xB3 +MAP_SAFFRON_MART = 0xB4 +MAP_SILPH_CO_1F = 0xB5 +MAP_SAFFRON_POKECENTER = 0xB6 +MAP_MR_PSYCHICS_HOUSE = 0xB7 +MAP_ROUTE_15_GATE_1F = 0xB8 +MAP_ROUTE_15_GATE_2F = 0xB9 +MAP_ROUTE_16_GATE_1F = 0xBA +MAP_ROUTE_16_GATE_2F = 0xBB +MAP_ROUTE_16_FLY_HOUSE = 0xBC +MAP_ROUTE_12_SUPER_ROD_HOUSE = 0xBD +MAP_ROUTE_18_GATE_1F = 0xBE +MAP_ROUTE_18_GATE_2F = 0xBF +MAP_SEAFOAM_ISLANDS_1F = 0xC0 +MAP_ROUTE_22_GATE = 0xC1 +MAP_VICTORY_ROAD_2F = 0xC2 +MAP_ROUTE_12_GATE_2F = 0xC3 +MAP_VERMILION_TRADE_HOUSE = 0xC4 +MAP_DIGLETTS_CAVE = 0xC5 +MAP_VICTORY_ROAD_3F = 0xC6 +MAP_ROCKET_HIDEOUT_B1F = 0xC7 +MAP_ROCKET_HIDEOUT_B2F = 0xC8 +MAP_ROCKET_HIDEOUT_B3F = 0xC9 +MAP_ROCKET_HIDEOUT_B4F = 0xCA +MAP_ROCKET_HIDEOUT_ELEVATOR = 0xCB +MAP_UNUSED_MAP_CC = 0xCC +MAP_UNUSED_MAP_CD = 0xCD +MAP_UNUSED_MAP_CE = 0xCE +MAP_SILPH_CO_2F = 0xCF +MAP_SILPH_CO_3F = 0xD0 +MAP_SILPH_CO_4F = 0xD1 +MAP_SILPH_CO_5F = 0xD2 +MAP_SILPH_CO_6F = 0xD3 +MAP_SILPH_CO_7F = 0xD4 +MAP_SILPH_CO_8F = 0xD5 +MAP_POKEMON_MANSION_2F = 0xD6 +MAP_POKEMON_MANSION_3F = 0xD7 +MAP_POKEMON_MANSION_B1F = 0xD8 +MAP_SAFARI_ZONE_EAST = 0xD9 +MAP_SAFARI_ZONE_NORTH = 0xDA +MAP_SAFARI_ZONE_WEST = 0xDB +MAP_SAFARI_ZONE_CENTER = 0xDC +MAP_SAFARI_ZONE_CENTER_REST_HOUSE = 0xDD +MAP_SAFARI_ZONE_SECRET_HOUSE = 0xDE +MAP_SAFARI_ZONE_WEST_REST_HOUSE = 0xDF +MAP_SAFARI_ZONE_EAST_REST_HOUSE = 0xE0 +MAP_SAFARI_ZONE_NORTH_REST_HOUSE = 0xE1 +MAP_CERULEAN_CAVE_2F = 0xE2 +MAP_CERULEAN_CAVE_B1F = 0xE3 +MAP_CERULEAN_CAVE_1F = 0xE4 +MAP_NAME_RATERS_HOUSE = 0xE5 +MAP_CERULEAN_BADGE_HOUSE = 0xE6 +MAP_UNUSED_MAP_E7 = 0xE7 +MAP_ROCK_TUNNEL_B1F = 0xE8 +MAP_SILPH_CO_9F = 0xE9 +MAP_SILPH_CO_10F = 0xEA +MAP_SILPH_CO_11F = 0xEB +MAP_SILPH_CO_ELEVATOR = 0xEC +MAP_UNUSED_MAP_ED = 0xED +MAP_UNUSED_MAP_EE = 0xEE +MAP_TRADE_CENTER = 0xEF +MAP_COLOSSEUM = 0xF0 +MAP_UNUSED_MAP_F1 = 0xF1 +MAP_UNUSED_MAP_F2 = 0xF2 +MAP_UNUSED_MAP_F3 = 0xF3 +MAP_UNUSED_MAP_F4 = 0xF4 +MAP_LORELEIS_ROOM = 0xF5 +MAP_BRUNOS_ROOM = 0xF6 +MAP_AGATHAS_ROOM = 0xF7 + +MAP_NAMES = [ +'PALLET TOWN', +'VIRIDIAN CITY', +'PEWTER CITY', +'CERULEAN CITY', +'LAVENDER TOWN', +'VERMILION CITY', +'CELADON CITY', +'FUCHSIA CITY', +'CINNABAR ISLAND', +'INDIGO PLATEAU', +'SAFFRON CITY', +'UNUSED MAP 0B', +'ROUTE 1', +'ROUTE 2', +'ROUTE 3', +'ROUTE 4', +'ROUTE 5', +'ROUTE 6', +'ROUTE 7', +'ROUTE 8', +'ROUTE 9', +'ROUTE 10', +'ROUTE 11', +'ROUTE 12', +'ROUTE 13', +'ROUTE 14', +'ROUTE 15', +'ROUTE 16', +'ROUTE 17', +'ROUTE 18', +'ROUTE 19', +'ROUTE 20', +'ROUTE 21', +'ROUTE 22', +'ROUTE 23', +'ROUTE 24', +'ROUTE 25', +'RED\'S HOUSE 1F', +'RED\'S HOUSE 2F', +'BLUE\'S HOUSE', +'OAK\'S LAB', +'VIRIDIAN POKECENTER', +'VIRIDIAN MART', +'VIRIDIAN SCHOOL HOUSE', +'VIRIDIAN NICKNAME HOUSE', +'VIRIDIAN GYM', +'DIGLETTS CAVE ROUTE 2', +'VIRIDIAN FOREST NORTH GATE', +'ROUTE 2 TRADE HOUSE', +'ROUTE 2 GATE', +'VIRIDIAN FOREST SOUTH GATE', +'VIRIDIAN FOREST', +'MUSEUM 1F', +'MUSEUM 2F', +'PEWTER GYM', +'PEWTER NIDORAN HOUSE', +'PEWTER MART', +'PEWTER SPEECH HOUSE', +'PEWTER POKECENTER', +'MT MOON 1F', +'MT MOON B1F', +'MT MOON B2F', +'CERULEAN TRASHED HOUSE', +'CERULEAN TRADE HOUSE', +'CERULEAN POKECENTER', +'CERULEAN GYM', +'BIKE SHOP', +'CERULEAN MART', +'MT MOON POKECENTER', +'CERULEAN TRASHED HOUSE COPY', +'ROUTE 5 GATE', +'UNDERGROUND PATH ROUTE 5', +'DAYCARE', +'ROUTE 6 GATE', +'UNDERGROUND PATH ROUTE 6', +'UNDERGROUND PATH ROUTE 6 COPY', +'ROUTE 7 GATE', +'UNDERGROUND PATH ROUTE 7', +'UNDERGROUND PATH ROUTE 7 COPY', +'ROUTE 8 GATE', +'UNDERGROUND PATH ROUTE 8', +'ROCK TUNNEL POKECENTER', +'ROCK TUNNEL 1F', +'POWER PLANT', +'ROUTE 11 GATE 1F', +'DIGLETT\'S CAVE ROUTE 11', +'ROUTE 11 GATE 2F', +'ROUTE 12 GATE 1F', +'BILLS HOUSE', +'VERMILION POKECENTER', +'POKEMON FAN CLUB', +'VERMILION MART', +'VERMILION GYM', +'VERMILION PIDGEY HOUSE', +'VERMILION DOCK', +'SS ANNE 1F', +'SS ANNE 2F', +'SS ANNE 3F', +'SS ANNE B1F', +'SS ANNE BOW', +'SS ANNE KITCHEN', +'SS ANNE CAPTAIN\'S ROOM', +'SS ANNE 1F ROOMS', +'SS ANNE 2F ROOMS', +'SS ANNE B1F ROOMS', +'UNUSED MAP 69', +'UNUSED MAP 6A', +'UNUSED MAP 6B', +'VICTORY ROAD 1F', +'UNUSED MAP 6D', +'UNUSED MAP 6E', +'UNUSED MAP 6F', +'UNUSED MAP 70', +'LANCES ROOM', +'UNUSED MAP 72', +'UNUSED MAP 73', +'UNUSED MAP 74', +'UNUSED MAP 75', +'HALL OF FAME', +'UNDERGROUND PATH NORTH SOUTH', +'CHAMPION\'S ROOM', +'UNDERGROUND PATH WEST EAST', +'CELADON MART 1F', +'CELADON MART 2F', +'CELADON MART 3F', +'CELADON MART 4F', +'CELADON MART ROOF', +'CELADON MART ELEVATOR', +'CELADON MANSION 1F', +'CELADON MANSION 2F', +'CELADON MANSION 3F', +'CELADON MANSION ROOF', +'CELADON MANSION ROOF HOUSE', +'CELADON POKECENTER', +'CELADON GYM', +'GAME CORNER', +'CELADON MART 5F', +'GAME CORNER PRIZE ROOM', +'CELADON DINER', +'CELADON CHIEF HOUSE', +'CELADON HOTEL', +'LAVENDER POKECENTER', +'POKEMON TOWER 1F', +'POKEMON TOWER 2F', +'POKEMON TOWER 3F', +'POKEMON TOWER 4F', +'POKEMON TOWER 5F', +'POKEMON TOWER 6F', +'POKEMON TOWER 7F', +'MR FUJIS HOUSE', +'LAVENDER MART', +'LAVENDER CUBONE HOUSE', +'FUCHSIA MART', +'FUCHSIA BILL\'S GRANDPAS HOUSE', +'FUCHSIA POKECENTER', +'WARDENS HOUSE', +'SAFARI ZONE GATE', +'FUCHSIA GYM', +'FUCHSIA MEETING ROOM', +'SEAFOAM ISLANDS B1F', +'SEAFOAM ISLANDS B2F', +'SEAFOAM ISLANDS B3F', +'SEAFOAM ISLANDS B4F', +'VERMILION OLD ROD HOUSE', +'FUCHSIA GOOD ROD HOUSE', +'POKEMON MANSION 1F', +'CINNABAR GYM', +'CINNABAR LAB', +'CINNABAR LAB TRADE ROOM', +'CINNABAR LAB METRONOME ROOM', +'CINNABAR LAB FOSSIL ROOM', +'CINNABAR POKECENTER', +'CINNABAR MART', +'CINNABAR MART COPY', +'INDIGO PLATEAU LOBBY', +'COPYCATS HOUSE 1F', +'COPYCATS HOUSE 2F', +'FIGHTING DOJO', +'SAFFRON GYM', +'SAFFRON PIDGEY HOUSE', +'SAFFRON MART', +'SILPH CO 1F', +'SAFFRON POKECENTER', +'MR PSYCHICS HOUSE', +'ROUTE 15 GATE 1F', +'ROUTE 15 GATE 2F', +'ROUTE 16 GATE 1F', +'ROUTE 16 GATE 2F', +'ROUTE 16 FLY HOUSE', +'ROUTE 12 SUPER ROD HOUSE', +'ROUTE 18 GATE 1F', +'ROUTE 18 GATE 2F', +'SEAFOAM ISLANDS 1F', +'ROUTE 22 GATE', +'VICTORY ROAD 2F', +'ROUTE 12 GATE 2F', +'VERMILION TRADE HOUSE', +'DIGLETTS CAVE', +'VICTORY ROAD 3F', +'ROCKET HIDEOUT B1F', +'ROCKET HIDEOUT B2F', +'ROCKET HIDEOUT B3F', +'ROCKET HIDEOUT B4F', +'ROCKET HIDEOUT ELEVATOR', +'UNUSED MAP CC', +'UNUSED MAP CD', +'UNUSED MAP CE', +'SILPH CO 2F', +'SILPH CO 3F', +'SILPH CO 4F', +'SILPH CO 5F', +'SILPH CO 6F', +'SILPH CO 7F', +'SILPH CO 8F', +'POKEMON MANSION 2F', +'POKEMON MANSION 3F', +'POKEMON MANSION B1F', +'SAFARI ZONE EAST', +'SAFARI ZONE NORTH', +'SAFARI ZONE WEST', +'SAFARI ZONE CENTER', +'SAFARI ZONE CENTER REST HOUSE', +'SAFARI ZONE SECRET HOUSE', +'SAFARI ZONE WEST REST HOUSE', +'SAFARI ZONE EAST REST HOUSE', +'SAFARI ZONE NORTH REST HOUSE', +'CERULEAN CAVE 2F', +'CERULEAN CAVE B1F', +'CERULEAN CAVE 1F', +'NAME RATER\'S HOUSE', +'CERULEAN BADGE HOUSE', +'UNUSED MAP E7', +'ROCK TUNNEL B1F', +'SILPH CO 9F', +'SILPH CO 10F', +'SILPH CO 11F', +'SILPH CO ELEVATOR', +'UNUSED MAP ED', +'UNUSED MAP EE', +'TRADE CENTER', +'COLOSSEUM', +'UNUSED MAP F1', +'UNUSED MAP F2', +'UNUSED MAP F3', +'UNUSED MAP F4', +'LORELEI\'S ROOM', +'BRUNO\'S ROOM', +'AGATHA\'S ROOM', +] + +STATUS_ASLEEP = 4 +STATUS_POISONED = 8 +STATUS_BURNED = 16 +STATUS_FROZEN = 32 +STATUS_PARALYZED = 64 + +MONSTER_NAMES = ( + "Bulbasaur", + "Ivysaur", + "Venusaur", + "Charmander", + "Charmeleon", + "Charizard", + "Squirtle", + "Wartortle", + "Blastoise", + "Caterpie", + "Metapod", + "Butterfree", + "Weedle", + "Kakuna", + "Beedrill", + "Pidgey", + "Pidgeotto", + "Pidgeot", + "Rattata", + "Raticate", + "Spearow", + "Fearow", + "Ekans", + "Arbok", + "Pikachu", + "Raichu", + "Sandshrew", + "Sandslash", + "Nidoran♀", + "Nidorina", + "Nidoqueen", + "Nidoran♂", + "Nidorino", + "Nidoking", + "Clefairy", + "Clefable", + "Vulpix", + "Ninetales", + "Jigglypuff", + "Wigglytuff", + "Zubat", + "Golbat", + "Oddish", + "Gloom", + "Vileplume", + "Paras", + "Parasect", + "Venonat", + "Venomoth", + "Diglett", + "Dugtrio", + "Meowth", + "Persian", + "Psyduck", + "Golduck", + "Mankey", + "Primeape", + "Growlithe", + "Arcanine", + "Poliwag", + "Poliwhirl", + "Poliwrath", + "Abra", + "Kadabra", + "Alakazam", + "Machop", + "Machoke", + "Machamp", + "Bellsprout", + "Weepinbell", + "Victreebel", + "Tentacool", + "Tentacruel", + "Geodude", + "Graveler", + "Golem", + "Ponyta", + "Rapidash", + "Slowpoke", + "Slowbro", + "Magnemite", + "Magneton", + "Farfetch’d", + "Doduo", + "Dodrio", + "Seel", + "Dewgong", + "Grimer", + "Muk", + "Shellder", + "Cloyster", + "Gastly", + "Haunter", + "Gengar", + "Onix", + "Drowzee", + "Hypno", + "Krabby", + "Kingler", + "Voltorb", + "Electrode", + "Exeggcute", + "Exeggutor", + "Cubone", + "Marowak", + "Hitmonlee", + "Hitmonchan", + "Lickitung", + "Koffing", + "Weezing", + "Rhyhorn", + "Rhydon", + "Chansey", + "Tangela", + "Kangaskhan", + "Horsea", + "Seadra", + "Goldeen", + "Seaking", + "Staryu", + "Starmie", + "Mr. Mime", + "Scyther", + "Jynx", + "Electabuzz", + "Magmar", + "Pinsir", + "Tauros", + "Magikarp", + "Gyarados", + "Lapras", + "Ditto", + "Eevee", + "Vaporeon", + "Jolteon", + "Flareon", + "Porygon", + "Omanyte", + "Omastar", + "Kabuto", + "Kabutops", + "Aerodactyl", + "Snorlax", + "Articuno", + "Zapdos", + "Moltres", + "Dratini", + "Dragonair", + "Dragonite", + "Mewtwo", + "Mew", +) + +POKEDEX_TO_INDEX_MAP = ( + (112, 0x01), + (115, 0x02), + (32, 0x03), + (35, 0x04), + (21, 0x05), + (100, 0x06), + (34, 0x07), + (80, 0x08), + (2, 0x09), + (103, 0x0A), + (108, 0x0B), + (102, 0x0C), + (88, 0x0D), + (94, 0x0E), + (29, 0x0F), + (31, 0x10), + (104, 0x11), + (111, 0x12), + (131, 0x13), + (59, 0x14), + (151, 0x15), + (130, 0x16), + (90, 0x17), + (72, 0x18), + (92, 0x19), + (123, 0x1A), + (120, 0x1B), + (9, 0x1C), + (127, 0x1D), + (114, 0x1E), + (58, 0x21), + (95, 0x22), + (22, 0x23), + (16, 0x24), + (79, 0x25), + (64, 0x26), + (75, 0x27), + (113, 0x28), + (67, 0x29), + (122, 0x2A), + (106, 0x2B), + (107, 0x2C), + (24, 0x2D), + (47, 0x2E), + (54, 0x2F), + (96, 0x30), + (76, 0x31), + (126, 0x33), + (125, 0x35), + (82, 0x36), + (109, 0x37), + (56, 0x39), + (86, 0x3A), + (50, 0x3B), + (128, 0x3C), + (83, 0x40), + (48, 0x41), + (149, 0x42), + (84, 0x46), + (60, 0x47), + (124, 0x48), + (146, 0x49), + (144, 0x4A), + (145, 0x4B), + (132, 0x4C), + (52, 0x4D), + (98, 0x4E), + (37, 0x52), + (38, 0x53), + (25, 0x54), + (26, 0x55), + (147, 0x58), + (148, 0x59), + (140, 0x5A), + (141, 0x5B), + (116, 0x5C), + (117, 0x5D), + (27, 0x60), + (28, 0x61), + (138, 0x62), + (139, 0x63), + (39, 0x64), + (40, 0x65), + (133, 0x66), + (136, 0x67), + (135, 0x68), + (134, 0x69), + (66, 0x6A), + (41, 0x6B), + (23, 0x6C), + (46, 0x6D), + (61, 0x6E), + (62, 0x6F), + (13, 0x70), + (14, 0x71), + (15, 0x72), + (85, 0x74), + (57, 0x75), + (51, 0x76), + (49, 0x77), + (87, 0x78), + (10, 0x7B), + (11, 0x7C), + (12, 0x7D), + (68, 0x7E), + (55, 0x80), + (97, 0x81), + (42, 0x82), + (150, 0x83), + (143, 0x84), + (129, 0x85), + (89, 0x88), + (99, 0x8A), + (91, 0x8B), + (101, 0x8D), + (36, 0x8E), + (110, 0x8F), + (53, 0x90), + (105, 0x91), + (93, 0x93), + (63, 0x94), + (65, 0x95), + (17, 0x96), + (18, 0x97), + (121, 0x98), + (1, 0x99), + (2, 0x9A), + (73, 0x9B), + (118, 0x9D), + (119, 0x9E), + (77, 0xA3), + (78, 0xA4), + (19, 0xA5), + (20, 0xA6), + (33, 0xA7), + (30, 0xA8), + (74, 0xA9), + (137, 0xAA), + (142, 0xAB), + (81, 0xAD), + (4, 0xB0), + (7, 0xB1), + (5, 0xB2), + (8, 0xB3), + (6, 0xB4), + (43, 0xB9), + (44, 0xBA), + (45, 0xBB), + (69, 0xBC), + (70, 0xBD), + (71, 0xBE), +) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.pxd b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.pxd new file mode 100644 index 000000000..499f68737 --- /dev/null +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.pxd @@ -0,0 +1,10 @@ +# +# License: See LICENSE.md file +# GitHub: https://github.com/Baekalfen/PyBoy +# +from libc.stdint cimport uint8_t +from pyboy.plugins.base_plugin cimport PyBoyGameWrapper +cimport cython + +cdef class GameWrapperPokemonGen1(PyBoyGameWrapper): + pass \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py new file mode 100644 index 000000000..59831a3f3 --- /dev/null +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py @@ -0,0 +1,429 @@ +# +# License: See LICENSE.md file +# GitHub: https://github.com/Baekalfen/PyBoy +# + +__pdoc__ = { + "GameWrapperPokemonGen1.cartridge_title": False, + "GameWrapperPokemonGen1.post_tick": False, +} + +import numpy as np +from pyboy.utils import WindowEvent +from pyboy.logger import logger +from ..base_plugin import PyBoyGameWrapper +from . import constants +from .utils import get_character_index + +PKMN_SIZE = 0x2C +BYTE_ORDER = 'big' + + +try: + from cython import compiled + cythonmode = compiled +except ImportError: + cythonmode = False + + +class GameWrapperPokemonGen1(PyBoyGameWrapper): + """ + This class wraps Pokemon Red, and provides easy access to score and a "fitness" score for AIs. + + If you call `print` on an instance of this object, it will show an overview of everything this object provides. + """ + cartridge_title = None + + def __init__(self, *args, **kwargs): + self.shape = (20, 18) + super().__init__(*args, game_area_section=(0, 0) + self.shape, game_area_wrap_around=True, **kwargs) + + def enabled(self): + return self.pyboy_argv.get("game_wrapper") and ((self.pyboy.cartridge_title() == "POKEMON RED") or + (self.pyboy.cartridge_title() == "POKEMON BLUE")) + + def post_tick(self): + self._tile_cache_invalid = True + self._sprite_cache_invalid = True + + scanline_parameters = self.pyboy.botsupport_manager().screen().tilemap_position_list() + WX = scanline_parameters[0][2] + WY = scanline_parameters[0][3] + self.use_background(WY != 0) + + def _get_screen_background_tilemap(self): + ### SIMILAR TO CURRENT pyboy.game_wrapper()._game_area_np(), BUT ONLY FOR BACKGROUND TILEMAP, SO NPC ARE SKIPPED + bsm = self.pyboy.botsupport_manager() + ((scx, scy), (wx, wy)) = bsm.screen().tilemap_position() + tilemap = np.array(bsm.tilemap_background()[:, :]) + return np.roll(np.roll(tilemap, -scy // 8, axis=0), -scx // 8, axis=1)[:18, :20] + + def _get_screen_walkable_matrix(self): + walkable_tiles_indexes = [] + collision_ptr = self.pyboy.get_memory_value(0xD530) + (self.pyboy.get_memory_value(0xD531) << 8) + tileset_type = self.pyboy.get_memory_value(0xFFD7) + if tileset_type > 0: + grass_tile_index = self.pyboy.get_memory_value(0xD535) + if grass_tile_index != 0xFF: + walkable_tiles_indexes.append(grass_tile_index + 0x100) + for i in range(0x180): + tile_index = self.pyboy.get_memory_value(collision_ptr + i) + if tile_index == 0xFF: + break + else: + walkable_tiles_indexes.append(tile_index + 0x100) + screen_tiles = self._get_screen_background_tilemap() + bottom_left_screen_tiles = screen_tiles[1:1 + screen_tiles.shape[0]:2, ::2] + walkable_matrix = np.isin(bottom_left_screen_tiles, walkable_tiles_indexes).astype(np.uint8) + return walkable_matrix + + def game_area_collision(self): + width = self.game_area_section[2] + height = self.game_area_section[3] + game_area = np.ndarray(shape=(height, width), dtype=np.uint32) + _collision = self._get_screen_walkable_matrix() + for i in range(height // 2): + for j in range(width // 2): + game_area[i * 2][j * 2:j*2 + 2] = _collision[i][j] + game_area[i*2 + 1][j * 2:j*2 + 2] = _collision[i][j] + return game_area + + def __repr__(self): + adjust = 4 + # yapf: disable + return ( + f"Pokemon Gen 1:\n" + + "Sprites on screen:\n" + + "\n".join([str(s) for s in self._sprites_on_screen()]) + + "\n" + + "Tiles on screen:\n" + + " "*5 + "".join([f"{i: <4}" for i in range(10)]) + "\n" + + "_"*(adjust*20+4) + + "\n" + + "\n".join( + [ + f"{i: <3}| " + "".join([str(tile).ljust(adjust) for tile in line]) + for i, line in enumerate(self.game_area()) + ] + ) + ) + # yapf: enable + + def get_int_at_address(self, address, size=2): + """Returns an integer from a given address of a specified size.""" + bytes = [] + for i in range(size): + bytes.append(self.pyboy.get_memory_value(address + i)) + return int.from_bytes(bytes, byteorder=BYTE_ORDER) + + def set_int_at_address(self, address, value, size=2): + """Sets an integer at a given address of a specified size.""" + bytes = value.to_bytes(2, byteorder=BYTE_ORDER) + i = 0 + for byte in bytes: + self.pyboy.set_memory_value(address + i, byte) + i += 1 + + def set_text(self, text, address): + """Sets text at address. + + Will always add a string terminator (80) at the end. + """ + i = 0 + for character in text: + try: + self.pyboy.set_memory_value(address + i, get_character_index(character)) + i += 1 + except: + pass + self.pyboy.set_memory_value(address + i, constants.STRING_TERMINATOR) + + def set_rom_text(self, text, bank, address): + i = 0 + for character in text: + try: + self.pyboy.override_memory_value(bank, address + i, get_character_index(character)) + i += 1 + except: + pass + + def set_player_name(self, name): + """ + Sets the player name. + + Args: + name (string): Name to be set (will be trimmed at 8 characters). + """ + self.set_text(name[:8], 0xD158) + + def get_player_name(self): + """ + Returns player name. + """ + return self.get_text(0xD158) + + def set_rival_name(self, name): + """ + Sets the rival name. + + Args: + name (string): Name to be set (will be trimmed at 8 characters). + """ + self.set_text(name[:8], 0xD34A) + + def get_rival_name(self): + """ + Returns rival name. + """ + return self.get_text(0xD34A) + + def get_text(self, address, cap = 16): + """ + Retrieves a string from a given address. + + Args: + address (int): Address from where to retrieve text from. + cap (int): Maximum expected length of string (default: 16). + """ + i = 0 + text = '' + while i < cap: + value = self.pyboy.get_memory_value(address + i) + try: + text += chr(value - constants.ASCII_DELTA) + except: + pass + if value == constants.STRING_TERMINATOR: + break + i += 1 + return text + + def set_palette_to_darkness(self): + self.pyboy.set_memory_value(0xD35D, 6) + + def set_player_monster(self, index, monster): + """ + Sets player monster at a given index. + + Args: + index (int): Which monster to change (0-5). + monster (int): Which type of monster to set. + """ + self.pyboy.set_memory_value(0xD16B + index, monster) + self.pyboy.set_memory_value(0xD164 + (index * PKMN_SIZE), monster) + + def get_player_monster(self, index): + """ + Returns player monster at a given index. + + Args: + index (int): Which monster to change (0-5). + """ + return self.pyboy.get_memory_value(0xD16B + index) + + def set_player_monster_nickname(self, index, text): + """ + Sets player monster's nickname at a given index. + + Args: + index (int): Which monster to change (0-5). + text (string): Nickname to set (will be trimmed at 10 characters). + """ + self.set_text(text[:10], 0xD2B5 + (index * PKMN_SIZE)) + + def get_player_monster_nickname(self, index): + """ + Returns player monster's nickname at a given index. + + Args: + index (int): Which monster (0-5). + """ + return self.get_text(0xD2B5 + (index * PKMN_SIZE)) + + def set_player_monster_move(self, index, move_index, move): + """ + Sets player monster's move at a given index. + + Args: + index (int): Which monster to change (0-5). + move_index (int): Which move to change (0-3). + move (int): Which type of move to set. + """ + self.pyboy.set_memory_value(0xD01C + (index * PKMN_SIZE) + move_index, move) + + def get_player_monster_move(self, index, move_index): + """ + Returns player monster's move at a given index. + + Args: + index (int): Which monster (0-5). + move_index (int): Which move to change (0-3). + """ + return self.pyboy.get_memory_value(0xD01C + (index * PKMN_SIZE) + move_index) + + def get_player_monster_current_hp(self, index): + """ + Returns player monster's current HP at a given index. + + Args: + index (int): Which monster (0-5). + """ + return self.get_int_at_address(0xD16C + (index * PKMN_SIZE)) + + def get_active_player_monster_current_hp(self): + return self.get_int_at_address(0xD015) + + def set_player_monster_current_hp(self, index, hp): + """ + Sets the current HP of a given player monster. + + Args: + index (int): Which monster to change (0-5). + hp (int): Health points. + """ + self.set_int_at_address(0xD16C + (index * PKMN_SIZE), hp) + + def set_active_player_monster_current_hp(self, hp): + self.set_int_at_address(0xD015, hp) + + def get_player_monster_max_hp(self, index): + """ + Returns player monster's max HP at a given index. + + Args: + index (int): Which monster (0-5). + """ + return self.get_int_at_address(0xD18D + (index * PKMN_SIZE)) + + def get_active_player_monster_max_hp(self): + return self.get_int_at_address(0xD023) + + def set_player_monster_max_hp(self, index, hp): + """ + Sets the max HP of a given player monster. + + Args: + index (int): Which monster to change (0-5). + hp (int): Health points. + """ + self.set_int_at_address(0xD18D + (index * PKMN_SIZE), hp) + + def set_active_player_monster_max_hp(self, hp): + return self.set_int_at_address(0xD023, hp) + + def set_player_monster_status(self, index, status): + """ + Sets the ailment status of a given player monster. + + Args: + index (int): Which monster to change (0-5). + status (int): Status to be set. + """ + assert status >= 0 and status < 0xFF + assert index < 6 + self.pyboy.set_memory_value(0xD16F + (index * PKMN_SIZE), status) + + def set_player_monster_asleep(self, index): + self.set_player_monster_status(index, constants.STATUS_ASLEEP) + + def set_player_monster_poisoned(self, index): + self.set_player_monster_status(index, constants.STATUS_POISONED) + + def set_player_monster_burned(self, index): + self.set_player_monster_status(index, constants.STATUS_BURNED) + + def set_player_monster_frozen(self, index): + self.set_player_monster_status(index, constants.STATUS_FROZEN) + + def set_player_monster_paralyzed(self, index): + self.set_player_monster_status(index, constants.STATUS_PARALYZED) + + def set_player_monster_no_ailment(self, index): + self.set_player_monster_status(index, 0) + + def get_player_money(self): + return self.get_int_at_address(0xD347, size=3) + + def set_active_player_monster_status(self, status): + self.pyboy.set_memory_value(0xD018, status) + + def set_active_player_monster_asleep(self): + self.set_active_player_monster_status(constants.STATUS_ASLEEP) + + def set_active_player_monster_poisoned(self): + self.set_active_player_monster_status(constants.STATUS_POISONED) + + def set_active_player_monster_burned(self): + self.set_active_player_monster_status(constants.STATUS_BURNED) + + def set_active_player_monster_frozen(self): + self.set_active_player_monster_status(constants.STATUS_FROZEN) + + def set_active_player_monster_paralyzed(self): + self.set_active_player_monster_status(constants.STATUS_PARALYZED) + + def set_active_player_monster_no_ailment(self): + self.set_active_player_monster_status(0) + + def set_active_player_monster_move(self, index, move): + self.pyboy.set_memory_value(0xD01C + index, move) + + def set_active_opponent_monster_move(self, index, move): + self.pyboy.set_memory_value(0xCFED + index, move) + + def set_active_player_monster_nickname(self, nickname): + self.set_text(nickname[:10], 0xD009) + + def set_active_opponent_monster_nickname(self, nickname): + self.set_text(nickname[:10], 0xCFDA) + + def set_active_opponent_monster_status(self, status): + self.pyboy.set_memory_value(0xCFE9, status) + + def set_active_opponent_monster_asleep(self): + self.set_active_opponent_monster_status(constants.STATUS_ASLEEP) + + def set_active_opponent_monster_poisoned(self): + self.set_active_opponent_monster_status(constants.STATUS_POISONED) + + def set_active_opponent_monster_burned(self): + self.set_active_opponent_monster_status(constants.STATUS_BURNED) + + def set_active_opponent_monster_frozen(self): + self.set_active_opponent_monster_status(constants.STATUS_FROZEN) + + def set_active_opponent_monster_paralyzed(self): + self.set_active_opponent_monster_status(constants.STATUS_PARALYZED) + + def set_active_opponent_monster_no_ailment(self): + self.set_active_opponent_monster_status(0) + + def heal_player_monster(self, index): + """ + Fully heals a player monster. + + Args: + index (int): Which monster to change (0-5). + """ + self.set_player_monster_no_ailment(index) + max_hp = self.get_player_monster_max_hp(index) + self.set_player_monster_current_hp(index, max_hp) + + def heal_active_player_monster(self): + self.set_active_player_monster_no_ailment() + max_hp = self.get_active_player_monster_max_hp() + self.set_active_player_monster_current_hp(max_hp) + + def is_battle_happening(self): + return self.pyboy.get_memory_value(0xD057) != 0 + + def get_current_map(self): + return self.pyboy.get_memory_value(0xD35E) + + def get_current_map_name(self): + return constants.MAP_NAMES[self.get_current_map()] + + def set_wild_encounter_rate(self, value): + self.pyboy.set_memory_value(0xD887, value) + + # TODO: Add player position functions diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/utils.py b/pyboy/plugins/game_wrapper_pokemon_gen1/utils.py new file mode 100644 index 000000000..77d52d432 --- /dev/null +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/utils.py @@ -0,0 +1,17 @@ +from .constants import ASCII_DELTA + +def get_character_index(character): + if character == ' ': + return 0x7F + if character == '?': + return 0xE6 + if character == '!': + return 0xE7 + if character == 'é': + return 0xBA + + index = ord(character) + if index > 47 and index < 58: + # number + return index + 197 + return index + ASCII_DELTA diff --git a/pyboy/plugins/manager.pxd b/pyboy/plugins/manager.pxd index 9a0edf012..79f1e844a 100644 --- a/pyboy/plugins/manager.pxd +++ b/pyboy/plugins/manager.pxd @@ -19,7 +19,7 @@ from pyboy.plugins.screenshot_recorder cimport ScreenshotRecorder from pyboy.plugins.game_wrapper_super_mario_land cimport GameWrapperSuperMarioLand from pyboy.plugins.game_wrapper_tetris cimport GameWrapperTetris from pyboy.plugins.game_wrapper_kirby_dream_land cimport GameWrapperKirbyDreamLand -from pyboy.plugins.game_wrapper_pokemon_gen1 cimport GameWrapperPokemonGen1 +from pyboy.plugins.game_wrapper_pokemon_gen1.game_wrapper_pokemon_gen1 cimport GameWrapperPokemonGen1 # imports end from pyboy.plugins.base_plugin cimport PyBoyPlugin, PyBoyWindowPlugin diff --git a/pyboy/plugins/manager.py b/pyboy/plugins/manager.py index ce37b8983..527be0050 100644 --- a/pyboy/plugins/manager.py +++ b/pyboy/plugins/manager.py @@ -18,7 +18,7 @@ from pyboy.plugins.game_wrapper_super_mario_land import GameWrapperSuperMarioLand # isort:skip from pyboy.plugins.game_wrapper_tetris import GameWrapperTetris # isort:skip from pyboy.plugins.game_wrapper_kirby_dream_land import GameWrapperKirbyDreamLand # isort:skip -from pyboy.plugins.game_wrapper_pokemon_gen1 import GameWrapperPokemonGen1 # isort:skip +from pyboy.plugins.game_wrapper_pokemon_gen1.game_wrapper_pokemon_gen1 import GameWrapperPokemonGen1 # isort:skip # imports end from pyboy.plugins.base_plugin import PyBoyGameWrapper From 75aa8beadb931215acf7a8241d8f7baf3fff2d1c Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Fri, 3 Nov 2023 19:27:36 -0400 Subject: [PATCH 04/74] Remove old pokemon_gen1 PLUGIN AS WELL AS now-renamed GameWrapperPokemonRed references --- pyboy/plugins/game_wrapper_pokemon_gen1.pxd | 10 - pyboy/plugins/game_wrapper_pokemon_gen1.py | 109 -- .../game_wrapper_pokemon_red/__init__.py | 1 - .../game_wrapper_pokemon_red/constants.py | 1399 ----------------- .../plugins/game_wrapper_pokemon_red/utils.py | 17 - .../game_wrapper_pokemon_red/wrapper.py | 385 ----- 6 files changed, 1921 deletions(-) delete mode 100644 pyboy/plugins/game_wrapper_pokemon_gen1.pxd delete mode 100644 pyboy/plugins/game_wrapper_pokemon_gen1.py delete mode 100644 pyboy/plugins/game_wrapper_pokemon_red/__init__.py delete mode 100644 pyboy/plugins/game_wrapper_pokemon_red/constants.py delete mode 100644 pyboy/plugins/game_wrapper_pokemon_red/utils.py delete mode 100644 pyboy/plugins/game_wrapper_pokemon_red/wrapper.py diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1.pxd b/pyboy/plugins/game_wrapper_pokemon_gen1.pxd deleted file mode 100644 index 38e041e95..000000000 --- a/pyboy/plugins/game_wrapper_pokemon_gen1.pxd +++ /dev/null @@ -1,10 +0,0 @@ -# -# License: See LICENSE.md file -# GitHub: https://github.com/Baekalfen/PyBoy -# -from libc.stdint cimport uint8_t -from pyboy.plugins.base_plugin cimport PyBoyGameWrapper -cimport cython - -cdef class GameWrapperPokemonGen1(PyBoyGameWrapper): - pass diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1.py b/pyboy/plugins/game_wrapper_pokemon_gen1.py deleted file mode 100644 index 1bf9a6c31..000000000 --- a/pyboy/plugins/game_wrapper_pokemon_gen1.py +++ /dev/null @@ -1,109 +0,0 @@ -# -# License: See LICENSE.md file -# GitHub: https://github.com/Baekalfen/PyBoy -# -__pdoc__ = { - "GameWrapperPokemonGen1.cartridge_title": False, - "GameWrapperPokemonGen1.post_tick": False, -} - -import logging - -import numpy as np - -from pyboy.utils import WindowEvent - -from .base_plugin import PyBoyGameWrapper - -logger = logging.getLogger(__name__) - -try: - from cython import compiled - cythonmode = compiled -except ImportError: - cythonmode = False - - -class GameWrapperPokemonGen1(PyBoyGameWrapper): - """ - This class wraps Pokemon Red/Blue, and provides basic access for AIs. - - If you call `print` on an instance of this object, it will show an overview of everything this object provides. - """ - cartridge_title = None - - def __init__(self, *args, **kwargs): - self.shape = (20, 18) - super().__init__(*args, game_area_section=(0, 0) + self.shape, game_area_wrap_around=True, **kwargs) - self.sprite_offset = 0x1000 - - def enabled(self): - return self.pyboy_argv.get("game_wrapper") and ((self.pyboy.cartridge_title() == "POKEMON RED") or - (self.pyboy.cartridge_title() == "POKEMON BLUE")) - - def post_tick(self): - self._tile_cache_invalid = True - self._sprite_cache_invalid = True - - scanline_parameters = self.pyboy.botsupport_manager().screen().tilemap_position_list() - WX = scanline_parameters[0][2] - WY = scanline_parameters[0][3] - self.use_background(WY != 0) - - def _get_screen_background_tilemap(self): - ### SIMILAR TO CURRENT pyboy.game_wrapper()._game_area_np(), BUT ONLY FOR BACKGROUND TILEMAP, SO NPC ARE SKIPPED - bsm = self.pyboy.botsupport_manager() - ((scx, scy), (wx, wy)) = bsm.screen().tilemap_position() - tilemap = np.array(bsm.tilemap_background()[:, :]) - return np.roll(np.roll(tilemap, -scy // 8, axis=0), -scx // 8, axis=1)[:18, :20] - - def _get_screen_walkable_matrix(self): - walkable_tiles_indexes = [] - collision_ptr = self.pyboy.get_memory_value(0xD530) + (self.pyboy.get_memory_value(0xD531) << 8) - tileset_type = self.pyboy.get_memory_value(0xFFD7) - if tileset_type > 0: - grass_tile_index = self.pyboy.get_memory_value(0xD535) - if grass_tile_index != 0xFF: - walkable_tiles_indexes.append(grass_tile_index + 0x100) - for i in range(0x180): - tile_index = self.pyboy.get_memory_value(collision_ptr + i) - if tile_index == 0xFF: - break - else: - walkable_tiles_indexes.append(tile_index + 0x100) - screen_tiles = self._get_screen_background_tilemap() - bottom_left_screen_tiles = screen_tiles[1:1 + screen_tiles.shape[0]:2, ::2] - walkable_matrix = np.isin(bottom_left_screen_tiles, walkable_tiles_indexes).astype(np.uint8) - return walkable_matrix - - def game_area_collision(self): - width = self.game_area_section[2] - height = self.game_area_section[3] - game_area = np.ndarray(shape=(height, width), dtype=np.uint32) - _collision = self._get_screen_walkable_matrix() - for i in range(height // 2): - for j in range(width // 2): - game_area[i * 2][j * 2:j*2 + 2] = _collision[i][j] - game_area[i*2 + 1][j * 2:j*2 + 2] = _collision[i][j] - return game_area - - def __repr__(self): - adjust = 4 - # yapf: disable - return ( - f"Pokemon Gen 1:\n" + - "Sprites on screen:\n" + - "\n".join([str(s) for s in self._sprites_on_screen()]) + - "\n" + - "Tiles on screen:\n" + - " "*5 + "".join([f"{i: <4}" for i in range(10)]) + "\n" + - "_"*(adjust*20+4) + - "\n" + - "\n".join( - [ - f"{i: <3}| " + "".join([str(tile).ljust(adjust) for tile in line]) - for i, line in enumerate(self.game_area()) - ] - ) - ) - # yapf: enable diff --git a/pyboy/plugins/game_wrapper_pokemon_red/__init__.py b/pyboy/plugins/game_wrapper_pokemon_red/__init__.py deleted file mode 100644 index 483ff23f9..000000000 --- a/pyboy/plugins/game_wrapper_pokemon_red/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .wrapper import GameWrapperPokemonRed diff --git a/pyboy/plugins/game_wrapper_pokemon_red/constants.py b/pyboy/plugins/game_wrapper_pokemon_red/constants.py deleted file mode 100644 index 4e857a32f..000000000 --- a/pyboy/plugins/game_wrapper_pokemon_red/constants.py +++ /dev/null @@ -1,1399 +0,0 @@ -STRING_TERMINATOR = 80 -ASCII_DELTA = 63 - -# Moves -MOVE_POUND = 0x01 -MOVE_KARATE_CHOP = 0x02 -MOVE_DOUBLESLAP = 0x03 -MOVE_COMET_PUNCH = 0x04 -MOVE_MEGA_PUNCH = 0x05 -MOVE_PAY_DAY = 0x06 -MOVE_FIRE_PUNCH = 0x07 -MOVE_ICE_PUNCH = 0x08 -MOVE_THUNDERPUNCH = 0x09 -MOVE_SCRATCH = 0x0a -MOVE_VICEGRIP = 0x0b -MOVE_GUILLOTINE = 0x0c -MOVE_RAZOR_WIND = 0x0d -MOVE_SWORDS_DANCE = 0x0e -MOVE_CUT = 0x0f -MOVE_GUST = 0x10 -MOVE_WING_ATTACK = 0x11 -MOVE_WHIRLWIND = 0x12 -MOVE_FLY = 0x13 -MOVE_BIND = 0x14 -MOVE_SLAM = 0x15 -MOVE_VINE_WHIP = 0x16 -MOVE_STOMP = 0x17 -MOVE_DOUBLE_KICK = 0x18 -MOVE_MEGA_KICK = 0x19 -MOVE_JUMP_KICK = 0x1a -MOVE_ROLLING_KICK = 0x1b -MOVE_SAND_ATTACK = 0x1c -MOVE_HEADBUTT = 0x1d -MOVE_HORN_ATTACK = 0x1e -MOVE_FURY_ATTACK = 0x1f -MOVE_HORN_DRILL = 0x20 -MOVE_TACKLE = 0x21 -MOVE_BODY_SLAM = 0x22 -MOVE_WRAP = 0x23 -MOVE_TAKE_DOWN = 0x24 -MOVE_THRASH = 0x25 -MOVE_DOUBLE_EDGE = 0x26 -MOVE_TAIL_WHIP = 0x27 -MOVE_POISON_STING = 0x28 -MOVE_TWINEEDLE = 0x29 -MOVE_PIN_MISSILE = 0x2a -MOVE_LEER = 0x2b -MOVE_BITE = 0x2c -MOVE_GROWL = 0x2d -MOVE_ROAR = 0x2e -MOVE_SING = 0x2f -MOVE_SUPERSONIC = 0x30 -MOVE_SONICBOOM = 0x31 -MOVE_DISABLE = 0x32 -MOVE_ACID = 0x33 -MOVE_EMBER = 0x34 -MOVE_FLAMETHROWER = 0x35 -MOVE_MIST = 0x36 -MOVE_WATER_GUN = 0x37 -MOVE_HYDRO_PUMP = 0x38 -MOVE_SURF = 0x39 -MOVE_ICE_BEAM = 0x3a -MOVE_BLIZZARD = 0x3b -MOVE_PSYBEAM = 0x3c -MOVE_BUBBLEBEAM = 0x3d -MOVE_AURORA_BEAM = 0x3e -MOVE_HYPER_BEAM = 0x3f -MOVE_PECK = 0x40 -MOVE_DRILL_PECK = 0x41 -MOVE_SUBMISSION = 0x42 -MOVE_LOW_KICK = 0x43 -MOVE_COUNTER = 0x44 -MOVE_SEISMIC_TOSS = 0x45 -MOVE_STRENGTH = 0x46 -MOVE_ABSORB = 0x47 -MOVE_MEGA_DRAIN = 0x48 -MOVE_LEECH_SEED = 0x49 -MOVE_GROWTH = 0x4a -MOVE_RAZOR_LEAF = 0x4b -MOVE_SOLARBEAM = 0x4c -MOVE_POISONPOWDER = 0x4d -MOVE_STUN_SPORE = 0x4e -MOVE_SLEEP_POWDER = 0x4f -MOVE_PETAL_DANCE = 0x50 -MOVE_STRING_SHOT = 0x51 -MOVE_DRAGON_RAGE = 0x52 -MOVE_FIRE_SPIN = 0x53 -MOVE_THUNDERSHOCK = 0x54 -MOVE_THUNDERBOLT = 0x55 -MOVE_THUNDER_WAVE = 0x56 -MOVE_THUNDER = 0x57 -MOVE_ROCK_THROW = 0x58 -MOVE_EARTHQUAKE = 0x59 -MOVE_FISSURE = 0x5a -MOVE_DIG = 0x5b -MOVE_TOXIC = 0x5c -MOVE_CONFUSION = 0x5d -MOVE_PSYCHIC_M = 0x5e -MOVE_HYPNOSIS = 0x5f -MOVE_MEDITATE = 0x60 -MOVE_AGILITY = 0x61 -MOVE_QUICK_ATTACK = 0x62 -MOVE_RAGE = 0x63 -MOVE_TELEPORT = 0x64 -MOVE_NIGHT_SHADE = 0x65 -MOVE_MIMIC = 0x66 -MOVE_SCREECH = 0x67 -MOVE_DOUBLE_TEAM = 0x68 -MOVE_RECOVER = 0x69 -MOVE_HARDEN = 0x6a -MOVE_MINIMIZE = 0x6b -MOVE_SMOKESCREEN = 0x6c -MOVE_CONFUSE_RAY = 0x6d -MOVE_WITHDRAW = 0x6e -MOVE_DEFENSE_CURL = 0x6f -MOVE_BARRIER = 0x70 -MOVE_LIGHT_SCREEN = 0x71 -MOVE_HAZE = 0x72 -MOVE_REFLECT = 0x73 -MOVE_FOCUS_ENERGY = 0x74 -MOVE_BIDE = 0x75 -MOVE_METRONOME = 0x76 -MOVE_MIRROR_MOVE = 0x77 -MOVE_SELFDESTRUCT = 0x78 -MOVE_EGG_BOMB = 0x79 -MOVE_LICK = 0x7a -MOVE_SMOG = 0x7b -MOVE_SLUDGE = 0x7c -MOVE_BONE_CLUB = 0x7d -MOVE_FIRE_BLAST = 0x7e -MOVE_WATERFALL = 0x7f -MOVE_CLAMP = 0x80 -MOVE_SWIFT = 0x81 -MOVE_SKULL_BASH = 0x82 -MOVE_SPIKE_CANNON = 0x83 -MOVE_CONSTRICT = 0x84 -MOVE_AMNESIA = 0x85 -MOVE_KINESIS = 0x86 -MOVE_SOFTBOILED = 0x87 -MOVE_HI_JUMP_KICK = 0x88 -MOVE_GLARE = 0x89 -MOVE_DREAM_EATER = 0x8a -MOVE_POISON_GAS = 0x8b -MOVE_BARRAGE = 0x8c -MOVE_LEECH_LIFE = 0x8d -MOVE_LOVELY_KISS = 0x8e -MOVE_SKY_ATTACK = 0x8f -MOVE_TRANSFORM = 0x90 -MOVE_BUBBLE = 0x91 -MOVE_DIZZY_PUNCH = 0x92 -MOVE_SPORE = 0x93 -MOVE_FLASH = 0x94 -MOVE_PSYWAVE = 0x95 -MOVE_SPLASH = 0x96 -MOVE_ACID_ARMOR = 0x97 -MOVE_CRABHAMMER = 0x98 -MOVE_EXPLOSION = 0x99 -MOVE_FURY_SWIPES = 0x9a -MOVE_BONEMERANG = 0x9b -MOVE_REST = 0x9c -MOVE_ROCK_SLIDE = 0x9d -MOVE_HYPER_FANG = 0x9e -MOVE_SHARPEN = 0x9f -MOVE_CONVERSION = 0xa0 -MOVE_TRI_ATTACK = 0xa1 -MOVE_SUPER_FANG = 0xa2 -MOVE_SLASH = 0xa3 -MOVE_SUBSTITUTE = 0xa4 - -MONSTER_RHYDON = 0x01 -MONSTER_KANGASKHAN = 0x02 -MONSTER_NIDORAN_M = 0x03 -MONSTER_CLEFAIRY = 0x04 -MONSTER_SPEAROW = 0x05 -MONSTER_VOLTORB = 0x06 -MONSTER_NIDOKING = 0x07 -MONSTER_SLOWBRO = 0x08 -MONSTER_IVYSAUR = 0x09 -MONSTER_EXEGGUTOR = 0x0A -MONSTER_LICKITUNG = 0x0B -MONSTER_EXEGGCUTE = 0x0C -MONSTER_GRIMER = 0x0D -MONSTER_GENGAR = 0x0E -MONSTER_NIDORAN_F = 0x0F -MONSTER_NIDOQUEEN = 0x10 -MONSTER_CUBONE = 0x11 -MONSTER_RHYHORN = 0x12 -MONSTER_LAPRAS = 0x13 -MONSTER_ARCANINE = 0x14 -MONSTER_MEW = 0x15 -MONSTER_GYARADOS = 0x16 -MONSTER_SHELLDER = 0x17 -MONSTER_TENTACOOL = 0x18 -MONSTER_GASTLY = 0x19 -MONSTER_SCYTHER = 0x1A -MONSTER_STARYU = 0x1B -MONSTER_BLASTOISE = 0x1C -MONSTER_PINSIR = 0x1D -MONSTER_TANGELA = 0x1E -MONSTER_MISSINGNO_1F = 0x1F -MONSTER_MISSINGNO_20 = 0x20 -MONSTER_GROWLITHE = 0x21 -MONSTER_ONIX = 0x22 -MONSTER_FEAROW = 0x23 -MONSTER_PIDGEY = 0x24 -MONSTER_SLOWPOKE = 0x25 -MONSTER_KADABRA = 0x26 -MONSTER_GRAVELER = 0x27 -MONSTER_CHANSEY = 0x28 -MONSTER_MACHOKE = 0x29 -MONSTER_MR_MIME = 0x2A -MONSTER_HITMONLEE = 0x2B -MONSTER_HITMONCHAN = 0x2C -MONSTER_ARBOK = 0x2D -MONSTER_PARASECT = 0x2E -MONSTER_PSYDUCK = 0x2F -MONSTER_DROWZEE = 0x30 -MONSTER_GOLEM = 0x31 -MONSTER_MISSINGNO_32 = 0x32 -MONSTER_MAGMAR = 0x33 -MONSTER_MISSINGNO_34 = 0x34 -MONSTER_ELECTABUZZ = 0x35 -MONSTER_MAGNETON = 0x36 -MONSTER_KOFFING = 0x37 -MONSTER_MISSINGNO_38 = 0x38 -MONSTER_MANKEY = 0x39 -MONSTER_SEEL = 0x3A -MONSTER_DIGLETT = 0x3B -MONSTER_TAUROS = 0x3C -MONSTER_MISSINGNO_3D = 0x3D -MONSTER_MISSINGNO_3E = 0x3E -MONSTER_MISSINGNO_3F = 0x3F -MONSTER_FARFETCHD = 0x40 -MONSTER_VENONAT = 0x41 -MONSTER_DRAGONITE = 0x42 -MONSTER_MISSINGNO_43 = 0x43 -MONSTER_MISSINGNO_44 = 0x44 -MONSTER_MISSINGNO_45 = 0x45 -MONSTER_DODUO = 0x46 -MONSTER_POLIWAG = 0x47 -MONSTER_JYNX = 0x48 -MONSTER_MOLTRES = 0x49 -MONSTER_ARTICUNO = 0x4A -MONSTER_ZAPDOS = 0x4B -MONSTER_DITTO = 0x4C -MONSTER_MEOWTH = 0x4D -MONSTER_KRABBY = 0x4E -MONSTER_MISSINGNO_4F = 0x4F -MONSTER_MISSINGNO_50 = 0x50 -MONSTER_MISSINGNO_51 = 0x51 -MONSTER_VULPIX = 0x52 -MONSTER_NINETALES = 0x53 -MONSTER_PIKACHU = 0x54 -MONSTER_RAICHU = 0x55 -MONSTER_MISSINGNO_56 = 0x56 -MONSTER_MISSINGNO_57 = 0x57 -MONSTER_DRATINI = 0x58 -MONSTER_DRAGONAIR = 0x59 -MONSTER_KABUTO = 0x5A -MONSTER_KABUTOPS = 0x5B -MONSTER_HORSEA = 0x5C -MONSTER_SEADRA = 0x5D -MONSTER_MISSINGNO_5E = 0x5E -MONSTER_MISSINGNO_5F = 0x5F -MONSTER_SANDSHREW = 0x60 -MONSTER_SANDSLASH = 0x61 -MONSTER_OMANYTE = 0x62 -MONSTER_OMASTAR = 0x63 -MONSTER_JIGGLYPUFF = 0x64 -MONSTER_WIGGLYTUFF = 0x65 -MONSTER_EEVEE = 0x66 -MONSTER_FLAREON = 0x67 -MONSTER_JOLTEON = 0x68 -MONSTER_VAPOREON = 0x69 -MONSTER_MACHOP = 0x6A -MONSTER_ZUBAT = 0x6B -MONSTER_EKANS = 0x6C -MONSTER_PARAS = 0x6D -MONSTER_POLIWHIRL = 0x6E -MONSTER_POLIWRATH = 0x6F -MONSTER_WEEDLE = 0x70 -MONSTER_KAKUNA = 0x71 -MONSTER_BEEDRILL = 0x72 -MONSTER_MISSINGNO_73 = 0x73 -MONSTER_DODRIO = 0x74 -MONSTER_PRIMEAPE = 0x75 -MONSTER_DUGTRIO = 0x76 -MONSTER_VENOMOTH = 0x77 -MONSTER_DEWGONG = 0x78 -MONSTER_MISSINGNO_79 = 0x79 -MONSTER_MISSINGNO_7A = 0x7A -MONSTER_CATERPIE = 0x7B -MONSTER_METAPOD = 0x7C -MONSTER_BUTTERFREE = 0x7D -MONSTER_MACHAMP = 0x7E -MONSTER_MISSINGNO_7F = 0x7F -MONSTER_GOLDUCK = 0x80 -MONSTER_HYPNO = 0x81 -MONSTER_GOLBAT = 0x82 -MONSTER_MEWTWO = 0x83 -MONSTER_SNORLAX = 0x84 -MONSTER_MAGIKARP = 0x85 -MONSTER_MISSINGNO_86 = 0x86 -MONSTER_MISSINGNO_87 = 0x87 -MONSTER_MUK = 0x88 -MONSTER_MISSINGNO_89 = 0x89 -MONSTER_KINGLER = 0x8A -MONSTER_CLOYSTER = 0x8B -MONSTER_MISSINGNO_8C = 0x8C -MONSTER_ELECTRODE = 0x8D -MONSTER_CLEFABLE = 0x8E -MONSTER_WEEZING = 0x8F -MONSTER_PERSIAN = 0x90 -MONSTER_MAROWAK = 0x91 -MONSTER_MISSINGNO_92 = 0x92 -MONSTER_HAUNTER = 0x93 -MONSTER_ABRA = 0x94 -MONSTER_ALAKAZAM = 0x95 -MONSTER_PIDGEOTTO = 0x96 -MONSTER_PIDGEOT = 0x97 -MONSTER_STARMIE = 0x98 -MONSTER_BULBASAUR = 0x99 -MONSTER_VENUSAUR = 0x9A -MONSTER_TENTACRUEL = 0x9B -MONSTER_MISSINGNO_9C = 0x9C -MONSTER_GOLDEEN = 0x9D -MONSTER_SEAKING = 0x9E -MONSTER_MISSINGNO_9F = 0x9F -MONSTER_MISSINGNO_A0 = 0xA0 -MONSTER_MISSINGNO_A1 = 0xA1 -MONSTER_MISSINGNO_A2 = 0xA2 -MONSTER_PONYTA = 0xA3 -MONSTER_RAPIDASH = 0xA4 -MONSTER_RATTATA = 0xA5 -MONSTER_RATICATE = 0xA6 -MONSTER_NIDORINO = 0xA7 -MONSTER_NIDORINA = 0xA8 -MONSTER_GEODUDE = 0xA9 -MONSTER_PORYGON = 0xAA -MONSTER_AERODACTYL = 0xAB -MONSTER_MISSINGNO_AC = 0xAC -MONSTER_MAGNEMITE = 0xAD -MONSTER_MISSINGNO_AE = 0xAE -MONSTER_MISSINGNO_AF = 0xAF -MONSTER_CHARMANDER = 0xB0 -MONSTER_SQUIRTLE = 0xB1 -MONSTER_CHARMELEON = 0xB2 -MONSTER_WARTORTLE = 0xB3 -MONSTER_CHARIZARD = 0xB4 -MONSTER_MISSINGNO_B5 = 0xB5 -MONSTER_FOSSIL_KABUTOPS = 0xB6 -MONSTER_FOSSIL_AERODACTYL = 0xB7 -MONSTER_MON_GHOST = 0xB8 -MONSTER_ODDISH = 0xB9 -MONSTER_GLOOM = 0xBA -MONSTER_VILEPLUME = 0xBB -MONSTER_BELLSPROUT = 0xBC -MONSTER_WEEPINBELL = 0xBD -MONSTER_VICTREEBEL = 0xBE - -ITEM_MASTER_BALL = 0x01 -ITEM_ULTRA_BALL = 0x02 -ITEM_GREAT_BALL = 0x03 -ITEM_POKE_BALL = 0x04 -ITEM_TOWN_MAP = 0x05 -ITEM_BICYCLE = 0x06 -ITEM_SURFBOARD = 0x07 -ITEM_SAFARI_BALL = 0x08 -ITEM_POKEDEX = 0x09 -ITEM_MOON_STONE = 0x0A -ITEM_ANTIDOTE = 0x0B -ITEM_BURN_HEAL = 0x0C -ITEM_ICE_HEAL = 0x0D -ITEM_AWAKENING = 0x0E -ITEM_PARLYZ_HEAL = 0x0F -ITEM_FULL_RESTORE = 0x10 -ITEM_MAX_POTION = 0x11 -ITEM_HYPER_POTION = 0x12 -ITEM_SUPER_POTION = 0x13 -ITEM_POTION = 0x14 -ITEM_BOULDERBADGE = 0x15 -ITEM_CASCADEBADGE = 0x16 -ITEM_THUNDERBADGE = 0x17 -ITEM_RAINBOWBADGE = 0x18 -ITEM_SOULBADGE = 0x19 -ITEM_MARSHBADGE = 0x1A -ITEM_VOLCANOBADGE = 0x1B -ITEM_EARTHBADGE = 0x1C -ITEM_ESCAPE_ROPE = 0x1D -ITEM_REPEL = 0x1E -ITEM_OLD_AMBER = 0x1F -ITEM_FIRE_STONE = 0x20 -ITEM_THUNDER_STONE = 0x21 -ITEM_WATER_STONE = 0x22 -ITEM_HP_UP = 0x23 -ITEM_PROTEIN = 0x24 -ITEM_IRON = 0x25 -ITEM_CARBOS = 0x26 -ITEM_CALCIUM = 0x27 -ITEM_RARE_CANDY = 0x28 -ITEM_DOME_FOSSIL = 0x29 -ITEM_HELIX_FOSSIL = 0x2A -ITEM_SECRET_KEY = 0x2B -ITEM_UNUSED_ITEM = 0x2C -ITEM_BIKE_VOUCHER = 0x2D -ITEM_X_ACCURACY = 0x2E -ITEM_LEAF_STONE = 0x2F -ITEM_CARD_KEY = 0x30 -ITEM_NUGGET = 0x31 -ITEM_PP_UP_2 = 0x32 -ITEM_POKE_DOLL = 0x33 -ITEM_FULL_HEAL = 0x34 -ITEM_REVIVE = 0x35 -ITEM_MAX_REVIVE = 0x36 -ITEM_GUARD_SPEC = 0x37 -ITEM_SUPER_REPEL = 0x38 -ITEM_MAX_REPEL = 0x39 -ITEM_DIRE_HIT = 0x3A -ITEM_COIN = 0x3B -ITEM_FRESH_WATER = 0x3C -ITEM_SODA_POP = 0x3D -ITEM_LEMONADE = 0x3E -ITEM_S_S_TICKET = 0x3F -ITEM_GOLD_TEETH = 0x40 -ITEM_X_ATTACK = 0x41 -ITEM_X_DEFEND = 0x42 -ITEM_X_SPEED = 0x43 -ITEM_X_SPECIAL = 0x44 -ITEM_COIN_CASE = 0x45 -ITEM_OAKS_PARCEL = 0x46 -ITEM_ITEMFINDER = 0x47 -ITEM_SILPH_SCOPE = 0x48 -ITEM_POKE_FLUTE = 0x49 -ITEM_LIFT_KEY = 0x4A -ITEM_EXP_ALL = 0x4B -ITEM_OLD_ROD = 0x4C -ITEM_GOOD_ROD = 0x4D -ITEM_SUPER_ROD = 0x4E -ITEM_PP_UP = 0x4F -ITEM_ETHER = 0x50 -ITEM_MAX_ETHER = 0x51 -ITEM_ELIXER = 0x52 -ITEM_MAX_ELIXER = 0x53 -ITEM_FLOOR_B2F = 0x54 -ITEM_FLOOR_B1F = 0x55 -ITEM_FLOOR_1F = 0x56 -ITEM_FLOOR_2F = 0x57 -ITEM_FLOOR_3F = 0x58 -ITEM_FLOOR_4F = 0x59 -ITEM_FLOOR_5F = 0x5A -ITEM_FLOOR_6F = 0x5B -ITEM_FLOOR_7F = 0x5C -ITEM_FLOOR_8F = 0x5D -ITEM_FLOOR_9F = 0x5E -ITEM_FLOOR_10F = 0x5F -ITEM_FLOOR_11F = 0x60 -ITEM_FLOOR_B4F = 0x61 -ITEM_HM_01 = 0xC4 -ITEM_HM_02 = 0xC5 -ITEM_HM_03 = 0xC6 -ITEM_HM_04 = 0xC7 -ITEM_HM_05 = 0xC8 -ITEM_TM_01 = 0xC9 -ITEM_TM_02 = 0xCA -ITEM_TM_03 = 0xCB -ITEM_TM_04 = 0xCC -ITEM_TM_05 = 0xCD -ITEM_TM_06 = 0xCE -ITEM_TM_07 = 0xCF -ITEM_TM_08 = 0xD0 -ITEM_TM_09 = 0xD1 -ITEM_TM_10 = 0xD2 -ITEM_TM_11 = 0xD3 -ITEM_TM_12 = 0xD4 -ITEM_TM_13 = 0xD5 -ITEM_TM_14 = 0xD6 -ITEM_TM_15 = 0xD7 -ITEM_TM_16 = 0xD8 -ITEM_TM_17 = 0xD9 -ITEM_TM_18 = 0xDA -ITEM_TM_19 = 0xDB -ITEM_TM_20 = 0xDC -ITEM_TM_21 = 0xDD -ITEM_TM_22 = 0xDE -ITEM_TM_23 = 0xDF -ITEM_TM_24 = 0xE0 -ITEM_TM_25 = 0xE1 -ITEM_TM_26 = 0xE2 -ITEM_TM_27 = 0xE3 -ITEM_TM_28 = 0xE4 -ITEM_TM_29 = 0xE5 -ITEM_TM_30 = 0xE6 -ITEM_TM_31 = 0xE7 -ITEM_TM_32 = 0xE8 -ITEM_TM_33 = 0xE9 -ITEM_TM_34 = 0xEA -ITEM_TM_35 = 0xEB -ITEM_TM_36 = 0xEC -ITEM_TM_37 = 0xED -ITEM_TM_38 = 0xEE -ITEM_TM_39 = 0xEF -ITEM_TM_40 = 0xF0 -ITEM_TM_41 = 0xF1 -ITEM_TM_42 = 0xF2 -ITEM_TM_43 = 0xF3 -ITEM_TM_44 = 0xF4 -ITEM_TM_45 = 0xF5 -ITEM_TM_46 = 0xF6 -ITEM_TM_47 = 0xF7 -ITEM_TM_48 = 0xF8 -ITEM_TM_49 = 0xF9 -ITEM_TM_50 = 0xFA - -SPRITE_RED = 0x01 -SPRITE_BLUE = 0x02 -SPRITE_OAK = 0x03 -SPRITE_BUG_CATCHER = 0x04 -SPRITE_SLOWBRO = 0x05 -SPRITE_LASS = 0x06 -SPRITE_BLACK_HAIR_BOY_1 = 0x07 -SPRITE_LITTLE_GIRL = 0x08 -SPRITE_BIRD = 0x09 -SPRITE_FAT_BALD_GUY = 0x0a -SPRITE_GAMBLER = 0x0b -SPRITE_BLACK_HAIR_BOY_2 = 0x0c -SPRITE_GIRL = 0x0d -SPRITE_HIKER = 0x0e -SPRITE_FOULARD_WOMAN = 0x0f -SPRITE_GENTLEMAN = 0x10 -SPRITE_DAISY = 0x11 -SPRITE_BIKER = 0x12 -SPRITE_SAILOR = 0x13 -SPRITE_COOK = 0x14 -SPRITE_BIKE_SHOP_GUY = 0x15 -SPRITE_MR_FUJI = 0x16 -SPRITE_GIOVANNI = 0x17 -SPRITE_ROCKET = 0x18 -SPRITE_MEDIUM = 0x19 -SPRITE_WAITER = 0x1a -SPRITE_ERIKA = 0x1b -SPRITE_MOM_GEISHA = 0x1c -SPRITE_BRUNETTE_GIRL = 0x1d -SPRITE_LANCE = 0x1e -SPRITE_OAK_SCIENTIST_AIDE = 0x1f -SPRITE_OAK_AIDE = 0x20 -SPRITE_ROCKER = 0x21 -SPRITE_SWIMMER = 0x22 -SPRITE_WHITE_PLAYER = 0x23 -SPRITE_GYM_HELPER = 0x24 -SPRITE_OLD_PERSON = 0x25 -SPRITE_MART_GUY = 0x26 -SPRITE_FISHER = 0x27 -SPRITE_OLD_MEDIUM_WOMAN = 0x28 -SPRITE_NURSE = 0x29 -SPRITE_CABLE_CLUB_WOMAN = 0x2a -SPRITE_MR_MASTERBALL = 0x2b -SPRITE_LAPRAS_GIVER = 0x2c -SPRITE_WARDEN = 0x2d -SPRITE_SS_CAPTAIN = 0x2e -SPRITE_FISHER2 = 0x2f -SPRITE_BLACKBELT = 0x30 -SPRITE_GUARD = 0x31 -SPRITE_COP_GUARD = 0x32 -SPRITE_MOM = 0x33 -SPRITE_BALDING_GUY = 0x34 -SPRITE_YOUNG_BOY = 0x35 -SPRITE_GAMEBOY_KID = 0x36 -SPRITE_GAMEBOY_KID_COPY = 0x37 -SPRITE_CLEFAIRY = 0x38 -SPRITE_AGATHA = 0x39 -SPRITE_BRUNO = 0x3a -SPRITE_LORELEI = 0x3b -SPRITE_SEEL = 0x3c -SPRITE_BALL = 0x3d -SPRITE_OMANYTE = 0x3e -SPRITE_BOULDER = 0x3f -SPRITE_PAPER_SHEET = 0x40 -SPRITE_BOOK_MAP_DEX = 0x41 -SPRITE_CLIPBOARD = 0x42 -SPRITE_SNORLAX = 0x43 -SPRITE_OLD_AMBER_COPY = 0x44 -SPRITE_OLD_AMBER = 0x45 -SPRITE_LYING_OLD_MAN_UNUSED_1 = 0x46 -SPRITE_LYING_OLD_MAN_UNUSED_2 = 0x47 -SPRITE_LYING_OLD_MAN = 0x48 - -MAP_PALLET_TOWN = 0x00 -MAP_VIRIDIAN_CITY = 0x01 -MAP_PEWTER_CITY = 0x02 -MAP_CERULEAN_CITY = 0x03 -MAP_LAVENDER_TOWN = 0x04 -MAP_VERMILION_CITY = 0x05 -MAP_CELADON_CITY = 0x06 -MAP_FUCHSIA_CITY = 0x07 -MAP_CINNABAR_ISLAND = 0x08 -MAP_INDIGO_PLATEAU = 0x09 -MAP_SAFFRON_CITY = 0x0A -MAP_UNUSED_MAP_0B = 0x0B -MAP_ROUTE_1 = 0x0C -MAP_ROUTE_2 = 0x0D -MAP_ROUTE_3 = 0x0E -MAP_ROUTE_4 = 0x0F -MAP_ROUTE_5 = 0x10 -MAP_ROUTE_6 = 0x11 -MAP_ROUTE_7 = 0x12 -MAP_ROUTE_8 = 0x13 -MAP_ROUTE_9 = 0x14 -MAP_ROUTE_10 = 0x15 -MAP_ROUTE_11 = 0x16 -MAP_ROUTE_12 = 0x17 -MAP_ROUTE_13 = 0x18 -MAP_ROUTE_14 = 0x19 -MAP_ROUTE_15 = 0x1A -MAP_ROUTE_16 = 0x1B -MAP_ROUTE_17 = 0x1C -MAP_ROUTE_18 = 0x1D -MAP_ROUTE_19 = 0x1E -MAP_ROUTE_20 = 0x1F -MAP_ROUTE_21 = 0x20 -MAP_ROUTE_22 = 0x21 -MAP_ROUTE_23 = 0x22 -MAP_ROUTE_24 = 0x23 -MAP_ROUTE_25 = 0x24 -MAP_REDS_HOUSE_1F = 0x25 -MAP_REDS_HOUSE_2F = 0x26 -MAP_BLUES_HOUSE = 0x27 -MAP_OAKS_LAB = 0x28 -MAP_VIRIDIAN_POKECENTER = 0x29 -MAP_VIRIDIAN_MART = 0x2A -MAP_VIRIDIAN_SCHOOL_HOUSE = 0x2B -MAP_VIRIDIAN_NICKNAME_HOUSE = 0x2C -MAP_VIRIDIAN_GYM = 0x2D -MAP_DIGLETTS_CAVE_ROUTE_2 = 0x2E -MAP_VIRIDIAN_FOREST_NORTH_GATE = 0x2F -MAP_ROUTE_2_TRADE_HOUSE = 0x30 -MAP_ROUTE_2_GATE = 0x31 -MAP_VIRIDIAN_FOREST_SOUTH_GATE = 0x32 -MAP_VIRIDIAN_FOREST = 0x33 -MAP_MUSEUM_1F = 0x34 -MAP_MUSEUM_2F = 0x35 -MAP_PEWTER_GYM = 0x36 -MAP_PEWTER_NIDORAN_HOUSE = 0x37 -MAP_PEWTER_MART = 0x38 -MAP_PEWTER_SPEECH_HOUSE = 0x39 -MAP_PEWTER_POKECENTER = 0x3A -MAP_MT_MOON_1F = 0x3B -MAP_MT_MOON_B1F = 0x3C -MAP_MT_MOON_B2F = 0x3D -MAP_CERULEAN_TRASHED_HOUSE = 0x3E -MAP_CERULEAN_TRADE_HOUSE = 0x3F -MAP_CERULEAN_POKECENTER = 0x40 -MAP_CERULEAN_GYM = 0x41 -MAP_BIKE_SHOP = 0x42 -MAP_CERULEAN_MART = 0x43 -MAP_MT_MOON_POKECENTER = 0x44 -MAP_CERULEAN_TRASHED_HOUSE_COPY = 0x45 -MAP_ROUTE_5_GATE = 0x46 -MAP_UNDERGROUND_PATH_ROUTE_5 = 0x47 -MAP_DAYCARE = 0x48 -MAP_ROUTE_6_GATE = 0x49 -MAP_UNDERGROUND_PATH_ROUTE_6 = 0x4A -MAP_UNDERGROUND_PATH_ROUTE_6_COPY = 0x4B -MAP_ROUTE_7_GATE = 0x4C -MAP_UNDERGROUND_PATH_ROUTE_7 = 0x4D -MAP_UNDERGROUND_PATH_ROUTE_7_COPY = 0x4E -MAP_ROUTE_8_GATE = 0x4F -MAP_UNDERGROUND_PATH_ROUTE_8 = 0x50 -MAP_ROCK_TUNNEL_POKECENTER = 0x51 -MAP_ROCK_TUNNEL_1F = 0x52 -MAP_POWER_PLANT = 0x53 -MAP_ROUTE_11_GATE_1F = 0x54 -MAP_DIGLETTS_CAVE_ROUTE_11 = 0x55 -MAP_ROUTE_11_GATE_2F = 0x56 -MAP_ROUTE_12_GATE_1F = 0x57 -MAP_BILLS_HOUSE = 0x58 -MAP_VERMILION_POKECENTER = 0x59 -MAP_POKEMON_FAN_CLUB = 0x5A -MAP_VERMILION_MART = 0x5B -MAP_VERMILION_GYM = 0x5C -MAP_VERMILION_PIDGEY_HOUSE = 0x5D -MAP_VERMILION_DOCK = 0x5E -MAP_SS_ANNE_1F = 0x5F -MAP_SS_ANNE_2F = 0x60 -MAP_SS_ANNE_3F = 0x61 -MAP_SS_ANNE_B1F = 0x62 -MAP_SS_ANNE_BOW = 0x63 -MAP_SS_ANNE_KITCHEN = 0x64 -MAP_SS_ANNE_CAPTAINS_ROOM = 0x65 -MAP_SS_ANNE_1F_ROOMS = 0x66 -MAP_SS_ANNE_2F_ROOMS = 0x67 -MAP_SS_ANNE_B1F_ROOMS = 0x68 -MAP_UNUSED_MAP_69 = 0x69 -MAP_UNUSED_MAP_6A = 0x6A -MAP_UNUSED_MAP_6B = 0x6B -MAP_VICTORY_ROAD_1F = 0x6C -MAP_UNUSED_MAP_6D = 0x6D -MAP_UNUSED_MAP_6E = 0x6E -MAP_UNUSED_MAP_6F = 0x6F -MAP_UNUSED_MAP_70 = 0x70 -MAP_LANCES_ROOM = 0x71 -MAP_UNUSED_MAP_72 = 0x72 -MAP_UNUSED_MAP_73 = 0x73 -MAP_UNUSED_MAP_74 = 0x74 -MAP_UNUSED_MAP_75 = 0x75 -MAP_HALL_OF_FAME = 0x76 -MAP_UNDERGROUND_PATH_NORTH_SOUTH = 0x77 -MAP_CHAMPIONS_ROOM = 0x78 -MAP_UNDERGROUND_PATH_WEST_EAST = 0x79 -MAP_CELADON_MART_1F = 0x7A -MAP_CELADON_MART_2F = 0x7B -MAP_CELADON_MART_3F = 0x7C -MAP_CELADON_MART_4F = 0x7D -MAP_CELADON_MART_ROOF = 0x7E -MAP_CELADON_MART_ELEVATOR = 0x7F -MAP_CELADON_MANSION_1F = 0x80 -MAP_CELADON_MANSION_2F = 0x81 -MAP_CELADON_MANSION_3F = 0x82 -MAP_CELADON_MANSION_ROOF = 0x83 -MAP_CELADON_MANSION_ROOF_HOUSE = 0x84 -MAP_CELADON_POKECENTER = 0x85 -MAP_CELADON_GYM = 0x86 -MAP_GAME_CORNER = 0x87 -MAP_CELADON_MART_5F = 0x88 -MAP_GAME_CORNER_PRIZE_ROOM = 0x89 -MAP_CELADON_DINER = 0x8A -MAP_CELADON_CHIEF_HOUSE = 0x8B -MAP_CELADON_HOTEL = 0x8C -MAP_LAVENDER_POKECENTER = 0x8D -MAP_POKEMON_TOWER_1F = 0x8E -MAP_POKEMON_TOWER_2F = 0x8F -MAP_POKEMON_TOWER_3F = 0x90 -MAP_POKEMON_TOWER_4F = 0x91 -MAP_POKEMON_TOWER_5F = 0x92 -MAP_POKEMON_TOWER_6F = 0x93 -MAP_POKEMON_TOWER_7F = 0x94 -MAP_MR_FUJIS_HOUSE = 0x95 -MAP_LAVENDER_MART = 0x96 -MAP_LAVENDER_CUBONE_HOUSE = 0x97 -MAP_FUCHSIA_MART = 0x98 -MAP_FUCHSIA_BILLS_GRANDPAS_HOUSE = 0x99 -MAP_FUCHSIA_POKECENTER = 0x9A -MAP_WARDENS_HOUSE = 0x9B -MAP_SAFARI_ZONE_GATE = 0x9C -MAP_FUCHSIA_GYM = 0x9D -MAP_FUCHSIA_MEETING_ROOM = 0x9E -MAP_SEAFOAM_ISLANDS_B1F = 0x9F -MAP_SEAFOAM_ISLANDS_B2F = 0xA0 -MAP_SEAFOAM_ISLANDS_B3F = 0xA1 -MAP_SEAFOAM_ISLANDS_B4F = 0xA2 -MAP_VERMILION_OLD_ROD_HOUSE = 0xA3 -MAP_FUCHSIA_GOOD_ROD_HOUSE = 0xA4 -MAP_POKEMON_MANSION_1F = 0xA5 -MAP_CINNABAR_GYM = 0xA6 -MAP_CINNABAR_LAB = 0xA7 -MAP_CINNABAR_LAB_TRADE_ROOM = 0xA8 -MAP_CINNABAR_LAB_METRONOME_ROOM = 0xA9 -MAP_CINNABAR_LAB_FOSSIL_ROOM = 0xAA -MAP_CINNABAR_POKECENTER = 0xAB -MAP_CINNABAR_MART = 0xAC -MAP_CINNABAR_MART_COPY = 0xAD -MAP_INDIGO_PLATEAU_LOBBY = 0xAE -MAP_COPYCATS_HOUSE_1F = 0xAF -MAP_COPYCATS_HOUSE_2F = 0xB0 -MAP_FIGHTING_DOJO = 0xB1 -MAP_SAFFRON_GYM = 0xB2 -MAP_SAFFRON_PIDGEY_HOUSE = 0xB3 -MAP_SAFFRON_MART = 0xB4 -MAP_SILPH_CO_1F = 0xB5 -MAP_SAFFRON_POKECENTER = 0xB6 -MAP_MR_PSYCHICS_HOUSE = 0xB7 -MAP_ROUTE_15_GATE_1F = 0xB8 -MAP_ROUTE_15_GATE_2F = 0xB9 -MAP_ROUTE_16_GATE_1F = 0xBA -MAP_ROUTE_16_GATE_2F = 0xBB -MAP_ROUTE_16_FLY_HOUSE = 0xBC -MAP_ROUTE_12_SUPER_ROD_HOUSE = 0xBD -MAP_ROUTE_18_GATE_1F = 0xBE -MAP_ROUTE_18_GATE_2F = 0xBF -MAP_SEAFOAM_ISLANDS_1F = 0xC0 -MAP_ROUTE_22_GATE = 0xC1 -MAP_VICTORY_ROAD_2F = 0xC2 -MAP_ROUTE_12_GATE_2F = 0xC3 -MAP_VERMILION_TRADE_HOUSE = 0xC4 -MAP_DIGLETTS_CAVE = 0xC5 -MAP_VICTORY_ROAD_3F = 0xC6 -MAP_ROCKET_HIDEOUT_B1F = 0xC7 -MAP_ROCKET_HIDEOUT_B2F = 0xC8 -MAP_ROCKET_HIDEOUT_B3F = 0xC9 -MAP_ROCKET_HIDEOUT_B4F = 0xCA -MAP_ROCKET_HIDEOUT_ELEVATOR = 0xCB -MAP_UNUSED_MAP_CC = 0xCC -MAP_UNUSED_MAP_CD = 0xCD -MAP_UNUSED_MAP_CE = 0xCE -MAP_SILPH_CO_2F = 0xCF -MAP_SILPH_CO_3F = 0xD0 -MAP_SILPH_CO_4F = 0xD1 -MAP_SILPH_CO_5F = 0xD2 -MAP_SILPH_CO_6F = 0xD3 -MAP_SILPH_CO_7F = 0xD4 -MAP_SILPH_CO_8F = 0xD5 -MAP_POKEMON_MANSION_2F = 0xD6 -MAP_POKEMON_MANSION_3F = 0xD7 -MAP_POKEMON_MANSION_B1F = 0xD8 -MAP_SAFARI_ZONE_EAST = 0xD9 -MAP_SAFARI_ZONE_NORTH = 0xDA -MAP_SAFARI_ZONE_WEST = 0xDB -MAP_SAFARI_ZONE_CENTER = 0xDC -MAP_SAFARI_ZONE_CENTER_REST_HOUSE = 0xDD -MAP_SAFARI_ZONE_SECRET_HOUSE = 0xDE -MAP_SAFARI_ZONE_WEST_REST_HOUSE = 0xDF -MAP_SAFARI_ZONE_EAST_REST_HOUSE = 0xE0 -MAP_SAFARI_ZONE_NORTH_REST_HOUSE = 0xE1 -MAP_CERULEAN_CAVE_2F = 0xE2 -MAP_CERULEAN_CAVE_B1F = 0xE3 -MAP_CERULEAN_CAVE_1F = 0xE4 -MAP_NAME_RATERS_HOUSE = 0xE5 -MAP_CERULEAN_BADGE_HOUSE = 0xE6 -MAP_UNUSED_MAP_E7 = 0xE7 -MAP_ROCK_TUNNEL_B1F = 0xE8 -MAP_SILPH_CO_9F = 0xE9 -MAP_SILPH_CO_10F = 0xEA -MAP_SILPH_CO_11F = 0xEB -MAP_SILPH_CO_ELEVATOR = 0xEC -MAP_UNUSED_MAP_ED = 0xED -MAP_UNUSED_MAP_EE = 0xEE -MAP_TRADE_CENTER = 0xEF -MAP_COLOSSEUM = 0xF0 -MAP_UNUSED_MAP_F1 = 0xF1 -MAP_UNUSED_MAP_F2 = 0xF2 -MAP_UNUSED_MAP_F3 = 0xF3 -MAP_UNUSED_MAP_F4 = 0xF4 -MAP_LORELEIS_ROOM = 0xF5 -MAP_BRUNOS_ROOM = 0xF6 -MAP_AGATHAS_ROOM = 0xF7 - -MAP_NAMES = [ -'PALLET TOWN', -'VIRIDIAN CITY', -'PEWTER CITY', -'CERULEAN CITY', -'LAVENDER TOWN', -'VERMILION CITY', -'CELADON CITY', -'FUCHSIA CITY', -'CINNABAR ISLAND', -'INDIGO PLATEAU', -'SAFFRON CITY', -'UNUSED MAP 0B', -'ROUTE 1', -'ROUTE 2', -'ROUTE 3', -'ROUTE 4', -'ROUTE 5', -'ROUTE 6', -'ROUTE 7', -'ROUTE 8', -'ROUTE 9', -'ROUTE 10', -'ROUTE 11', -'ROUTE 12', -'ROUTE 13', -'ROUTE 14', -'ROUTE 15', -'ROUTE 16', -'ROUTE 17', -'ROUTE 18', -'ROUTE 19', -'ROUTE 20', -'ROUTE 21', -'ROUTE 22', -'ROUTE 23', -'ROUTE 24', -'ROUTE 25', -'RED\'S HOUSE 1F', -'RED\'S HOUSE 2F', -'BLUE\'S HOUSE', -'OAK\'S LAB', -'VIRIDIAN POKECENTER', -'VIRIDIAN MART', -'VIRIDIAN SCHOOL HOUSE', -'VIRIDIAN NICKNAME HOUSE', -'VIRIDIAN GYM', -'DIGLETTS CAVE ROUTE 2', -'VIRIDIAN FOREST NORTH GATE', -'ROUTE 2 TRADE HOUSE', -'ROUTE 2 GATE', -'VIRIDIAN FOREST SOUTH GATE', -'VIRIDIAN FOREST', -'MUSEUM 1F', -'MUSEUM 2F', -'PEWTER GYM', -'PEWTER NIDORAN HOUSE', -'PEWTER MART', -'PEWTER SPEECH HOUSE', -'PEWTER POKECENTER', -'MT MOON 1F', -'MT MOON B1F', -'MT MOON B2F', -'CERULEAN TRASHED HOUSE', -'CERULEAN TRADE HOUSE', -'CERULEAN POKECENTER', -'CERULEAN GYM', -'BIKE SHOP', -'CERULEAN MART', -'MT MOON POKECENTER', -'CERULEAN TRASHED HOUSE COPY', -'ROUTE 5 GATE', -'UNDERGROUND PATH ROUTE 5', -'DAYCARE', -'ROUTE 6 GATE', -'UNDERGROUND PATH ROUTE 6', -'UNDERGROUND PATH ROUTE 6 COPY', -'ROUTE 7 GATE', -'UNDERGROUND PATH ROUTE 7', -'UNDERGROUND PATH ROUTE 7 COPY', -'ROUTE 8 GATE', -'UNDERGROUND PATH ROUTE 8', -'ROCK TUNNEL POKECENTER', -'ROCK TUNNEL 1F', -'POWER PLANT', -'ROUTE 11 GATE 1F', -'DIGLETT\'S CAVE ROUTE 11', -'ROUTE 11 GATE 2F', -'ROUTE 12 GATE 1F', -'BILLS HOUSE', -'VERMILION POKECENTER', -'POKEMON FAN CLUB', -'VERMILION MART', -'VERMILION GYM', -'VERMILION PIDGEY HOUSE', -'VERMILION DOCK', -'SS ANNE 1F', -'SS ANNE 2F', -'SS ANNE 3F', -'SS ANNE B1F', -'SS ANNE BOW', -'SS ANNE KITCHEN', -'SS ANNE CAPTAIN\'S ROOM', -'SS ANNE 1F ROOMS', -'SS ANNE 2F ROOMS', -'SS ANNE B1F ROOMS', -'UNUSED MAP 69', -'UNUSED MAP 6A', -'UNUSED MAP 6B', -'VICTORY ROAD 1F', -'UNUSED MAP 6D', -'UNUSED MAP 6E', -'UNUSED MAP 6F', -'UNUSED MAP 70', -'LANCES ROOM', -'UNUSED MAP 72', -'UNUSED MAP 73', -'UNUSED MAP 74', -'UNUSED MAP 75', -'HALL OF FAME', -'UNDERGROUND PATH NORTH SOUTH', -'CHAMPION\'S ROOM', -'UNDERGROUND PATH WEST EAST', -'CELADON MART 1F', -'CELADON MART 2F', -'CELADON MART 3F', -'CELADON MART 4F', -'CELADON MART ROOF', -'CELADON MART ELEVATOR', -'CELADON MANSION 1F', -'CELADON MANSION 2F', -'CELADON MANSION 3F', -'CELADON MANSION ROOF', -'CELADON MANSION ROOF HOUSE', -'CELADON POKECENTER', -'CELADON GYM', -'GAME CORNER', -'CELADON MART 5F', -'GAME CORNER PRIZE ROOM', -'CELADON DINER', -'CELADON CHIEF HOUSE', -'CELADON HOTEL', -'LAVENDER POKECENTER', -'POKEMON TOWER 1F', -'POKEMON TOWER 2F', -'POKEMON TOWER 3F', -'POKEMON TOWER 4F', -'POKEMON TOWER 5F', -'POKEMON TOWER 6F', -'POKEMON TOWER 7F', -'MR FUJIS HOUSE', -'LAVENDER MART', -'LAVENDER CUBONE HOUSE', -'FUCHSIA MART', -'FUCHSIA BILL\'S GRANDPAS HOUSE', -'FUCHSIA POKECENTER', -'WARDENS HOUSE', -'SAFARI ZONE GATE', -'FUCHSIA GYM', -'FUCHSIA MEETING ROOM', -'SEAFOAM ISLANDS B1F', -'SEAFOAM ISLANDS B2F', -'SEAFOAM ISLANDS B3F', -'SEAFOAM ISLANDS B4F', -'VERMILION OLD ROD HOUSE', -'FUCHSIA GOOD ROD HOUSE', -'POKEMON MANSION 1F', -'CINNABAR GYM', -'CINNABAR LAB', -'CINNABAR LAB TRADE ROOM', -'CINNABAR LAB METRONOME ROOM', -'CINNABAR LAB FOSSIL ROOM', -'CINNABAR POKECENTER', -'CINNABAR MART', -'CINNABAR MART COPY', -'INDIGO PLATEAU LOBBY', -'COPYCATS HOUSE 1F', -'COPYCATS HOUSE 2F', -'FIGHTING DOJO', -'SAFFRON GYM', -'SAFFRON PIDGEY HOUSE', -'SAFFRON MART', -'SILPH CO 1F', -'SAFFRON POKECENTER', -'MR PSYCHICS HOUSE', -'ROUTE 15 GATE 1F', -'ROUTE 15 GATE 2F', -'ROUTE 16 GATE 1F', -'ROUTE 16 GATE 2F', -'ROUTE 16 FLY HOUSE', -'ROUTE 12 SUPER ROD HOUSE', -'ROUTE 18 GATE 1F', -'ROUTE 18 GATE 2F', -'SEAFOAM ISLANDS 1F', -'ROUTE 22 GATE', -'VICTORY ROAD 2F', -'ROUTE 12 GATE 2F', -'VERMILION TRADE HOUSE', -'DIGLETTS CAVE', -'VICTORY ROAD 3F', -'ROCKET HIDEOUT B1F', -'ROCKET HIDEOUT B2F', -'ROCKET HIDEOUT B3F', -'ROCKET HIDEOUT B4F', -'ROCKET HIDEOUT ELEVATOR', -'UNUSED MAP CC', -'UNUSED MAP CD', -'UNUSED MAP CE', -'SILPH CO 2F', -'SILPH CO 3F', -'SILPH CO 4F', -'SILPH CO 5F', -'SILPH CO 6F', -'SILPH CO 7F', -'SILPH CO 8F', -'POKEMON MANSION 2F', -'POKEMON MANSION 3F', -'POKEMON MANSION B1F', -'SAFARI ZONE EAST', -'SAFARI ZONE NORTH', -'SAFARI ZONE WEST', -'SAFARI ZONE CENTER', -'SAFARI ZONE CENTER REST HOUSE', -'SAFARI ZONE SECRET HOUSE', -'SAFARI ZONE WEST REST HOUSE', -'SAFARI ZONE EAST REST HOUSE', -'SAFARI ZONE NORTH REST HOUSE', -'CERULEAN CAVE 2F', -'CERULEAN CAVE B1F', -'CERULEAN CAVE 1F', -'NAME RATER\'S HOUSE', -'CERULEAN BADGE HOUSE', -'UNUSED MAP E7', -'ROCK TUNNEL B1F', -'SILPH CO 9F', -'SILPH CO 10F', -'SILPH CO 11F', -'SILPH CO ELEVATOR', -'UNUSED MAP ED', -'UNUSED MAP EE', -'TRADE CENTER', -'COLOSSEUM', -'UNUSED MAP F1', -'UNUSED MAP F2', -'UNUSED MAP F3', -'UNUSED MAP F4', -'LORELEI\'S ROOM', -'BRUNO\'S ROOM', -'AGATHA\'S ROOM', -] - -STATUS_ASLEEP = 4 -STATUS_POISONED = 8 -STATUS_BURNED = 16 -STATUS_FROZEN = 32 -STATUS_PARALYZED = 64 - -MONSTER_NAMES = ( - "Bulbasaur", - "Ivysaur", - "Venusaur", - "Charmander", - "Charmeleon", - "Charizard", - "Squirtle", - "Wartortle", - "Blastoise", - "Caterpie", - "Metapod", - "Butterfree", - "Weedle", - "Kakuna", - "Beedrill", - "Pidgey", - "Pidgeotto", - "Pidgeot", - "Rattata", - "Raticate", - "Spearow", - "Fearow", - "Ekans", - "Arbok", - "Pikachu", - "Raichu", - "Sandshrew", - "Sandslash", - "Nidoran♀", - "Nidorina", - "Nidoqueen", - "Nidoran♂", - "Nidorino", - "Nidoking", - "Clefairy", - "Clefable", - "Vulpix", - "Ninetales", - "Jigglypuff", - "Wigglytuff", - "Zubat", - "Golbat", - "Oddish", - "Gloom", - "Vileplume", - "Paras", - "Parasect", - "Venonat", - "Venomoth", - "Diglett", - "Dugtrio", - "Meowth", - "Persian", - "Psyduck", - "Golduck", - "Mankey", - "Primeape", - "Growlithe", - "Arcanine", - "Poliwag", - "Poliwhirl", - "Poliwrath", - "Abra", - "Kadabra", - "Alakazam", - "Machop", - "Machoke", - "Machamp", - "Bellsprout", - "Weepinbell", - "Victreebel", - "Tentacool", - "Tentacruel", - "Geodude", - "Graveler", - "Golem", - "Ponyta", - "Rapidash", - "Slowpoke", - "Slowbro", - "Magnemite", - "Magneton", - "Farfetch’d", - "Doduo", - "Dodrio", - "Seel", - "Dewgong", - "Grimer", - "Muk", - "Shellder", - "Cloyster", - "Gastly", - "Haunter", - "Gengar", - "Onix", - "Drowzee", - "Hypno", - "Krabby", - "Kingler", - "Voltorb", - "Electrode", - "Exeggcute", - "Exeggutor", - "Cubone", - "Marowak", - "Hitmonlee", - "Hitmonchan", - "Lickitung", - "Koffing", - "Weezing", - "Rhyhorn", - "Rhydon", - "Chansey", - "Tangela", - "Kangaskhan", - "Horsea", - "Seadra", - "Goldeen", - "Seaking", - "Staryu", - "Starmie", - "Mr. Mime", - "Scyther", - "Jynx", - "Electabuzz", - "Magmar", - "Pinsir", - "Tauros", - "Magikarp", - "Gyarados", - "Lapras", - "Ditto", - "Eevee", - "Vaporeon", - "Jolteon", - "Flareon", - "Porygon", - "Omanyte", - "Omastar", - "Kabuto", - "Kabutops", - "Aerodactyl", - "Snorlax", - "Articuno", - "Zapdos", - "Moltres", - "Dratini", - "Dragonair", - "Dragonite", - "Mewtwo", - "Mew", -) - -POKEDEX_TO_INDEX_MAP = ( - (112, 0x01), - (115, 0x02), - (32, 0x03), - (35, 0x04), - (21, 0x05), - (100, 0x06), - (34, 0x07), - (80, 0x08), - (2, 0x09), - (103, 0x0A), - (108, 0x0B), - (102, 0x0C), - (88, 0x0D), - (94, 0x0E), - (29, 0x0F), - (31, 0x10), - (104, 0x11), - (111, 0x12), - (131, 0x13), - (59, 0x14), - (151, 0x15), - (130, 0x16), - (90, 0x17), - (72, 0x18), - (92, 0x19), - (123, 0x1A), - (120, 0x1B), - (9, 0x1C), - (127, 0x1D), - (114, 0x1E), - (58, 0x21), - (95, 0x22), - (22, 0x23), - (16, 0x24), - (79, 0x25), - (64, 0x26), - (75, 0x27), - (113, 0x28), - (67, 0x29), - (122, 0x2A), - (106, 0x2B), - (107, 0x2C), - (24, 0x2D), - (47, 0x2E), - (54, 0x2F), - (96, 0x30), - (76, 0x31), - (126, 0x33), - (125, 0x35), - (82, 0x36), - (109, 0x37), - (56, 0x39), - (86, 0x3A), - (50, 0x3B), - (128, 0x3C), - (83, 0x40), - (48, 0x41), - (149, 0x42), - (84, 0x46), - (60, 0x47), - (124, 0x48), - (146, 0x49), - (144, 0x4A), - (145, 0x4B), - (132, 0x4C), - (52, 0x4D), - (98, 0x4E), - (37, 0x52), - (38, 0x53), - (25, 0x54), - (26, 0x55), - (147, 0x58), - (148, 0x59), - (140, 0x5A), - (141, 0x5B), - (116, 0x5C), - (117, 0x5D), - (27, 0x60), - (28, 0x61), - (138, 0x62), - (139, 0x63), - (39, 0x64), - (40, 0x65), - (133, 0x66), - (136, 0x67), - (135, 0x68), - (134, 0x69), - (66, 0x6A), - (41, 0x6B), - (23, 0x6C), - (46, 0x6D), - (61, 0x6E), - (62, 0x6F), - (13, 0x70), - (14, 0x71), - (15, 0x72), - (85, 0x74), - (57, 0x75), - (51, 0x76), - (49, 0x77), - (87, 0x78), - (10, 0x7B), - (11, 0x7C), - (12, 0x7D), - (68, 0x7E), - (55, 0x80), - (97, 0x81), - (42, 0x82), - (150, 0x83), - (143, 0x84), - (129, 0x85), - (89, 0x88), - (99, 0x8A), - (91, 0x8B), - (101, 0x8D), - (36, 0x8E), - (110, 0x8F), - (53, 0x90), - (105, 0x91), - (93, 0x93), - (63, 0x94), - (65, 0x95), - (17, 0x96), - (18, 0x97), - (121, 0x98), - (1, 0x99), - (2, 0x9A), - (73, 0x9B), - (118, 0x9D), - (119, 0x9E), - (77, 0xA3), - (78, 0xA4), - (19, 0xA5), - (20, 0xA6), - (33, 0xA7), - (30, 0xA8), - (74, 0xA9), - (137, 0xAA), - (142, 0xAB), - (81, 0xAD), - (4, 0xB0), - (7, 0xB1), - (5, 0xB2), - (8, 0xB3), - (6, 0xB4), - (43, 0xB9), - (44, 0xBA), - (45, 0xBB), - (69, 0xBC), - (70, 0xBD), - (71, 0xBE), -) diff --git a/pyboy/plugins/game_wrapper_pokemon_red/utils.py b/pyboy/plugins/game_wrapper_pokemon_red/utils.py deleted file mode 100644 index 77d52d432..000000000 --- a/pyboy/plugins/game_wrapper_pokemon_red/utils.py +++ /dev/null @@ -1,17 +0,0 @@ -from .constants import ASCII_DELTA - -def get_character_index(character): - if character == ' ': - return 0x7F - if character == '?': - return 0xE6 - if character == '!': - return 0xE7 - if character == 'é': - return 0xBA - - index = ord(character) - if index > 47 and index < 58: - # number - return index + 197 - return index + ASCII_DELTA diff --git a/pyboy/plugins/game_wrapper_pokemon_red/wrapper.py b/pyboy/plugins/game_wrapper_pokemon_red/wrapper.py deleted file mode 100644 index b363c5455..000000000 --- a/pyboy/plugins/game_wrapper_pokemon_red/wrapper.py +++ /dev/null @@ -1,385 +0,0 @@ -# -# License: See LICENSE.md file -# GitHub: https://github.com/Baekalfen/PyBoy -# - -__pdoc__ = { - "GameWrapperPokemonRed.cartridge_title": False, - "GameWrapperPokemonRed.post_tick": False, -} - -from pyboy.utils import WindowEvent -from pyboy.logger import logger -from ..base_plugin import PyBoyGameWrapper -from . import constants -from .utils import get_character_index - -PKMN_SIZE = 0x2C -BYTE_ORDER = 'big' - - -try: - from cython import compiled - cythonmode = compiled -except ImportError: - cythonmode = False - - -class GameWrapperPokemonRed(PyBoyGameWrapper): - """ - This class wraps Pokemon Red, and provides easy access to score and a "fitness" score for AIs. - - If you call `print` on an instance of this object, it will show an overview of everything this object provides. - """ - cartridge_title = "POKEMON RED" - - def __init__(self, *args, **kwargs): - # TODO: Determine proper size - self.shape = (20, 16) - """The shape of the game area""" - super().__init__(*args, game_area_section=(0, 0) + self.shape, game_area_wrap_around=True, **kwargs) - - def start_game(self, timer_div=None): - """ - Call this function right after initializing PyBoy. This will navigate through menus to start the game at the - first playable state. - - The state of the emulator is saved, and using `reset_game`, you can get back to this point of the game - instantly. - - Kwargs: - timer_div (int): Replace timer's DIV register with this value. Use `None` to randomize. - """ - while self.get_player_name() != 'NINTEN': # Player is NINTEN on start screen - self.pyboy.tick() - self.pyboy.send_input(WindowEvent.PRESS_BUTTON_START) - self.pyboy.tick() - PyBoyGameWrapper.start_game(self, timer_div=timer_div) - - def reset_game(self, timer_div=None): - """ - After calling `start_game`, you can call this method at any time to reset the game. - - Kwargs: - timer_div (int): Replace timer's DIV register with this value. Use `None` to randomize. - """ - PyBoyGameWrapper.reset_game(self, timer_div=timer_div) - - def get_int_at_address(self, address, size=2): - """Returns an integer from a given address of a specified size.""" - bytes = [] - for i in range(size): - bytes.append(self.pyboy.get_memory_value(address + i)) - return int.from_bytes(bytes, byteorder=BYTE_ORDER) - - def set_int_at_address(self, address, value, size=2): - """Sets an integer at a given address of a specified size.""" - bytes = value.to_bytes(2, byteorder=BYTE_ORDER) - i = 0 - for byte in bytes: - self.pyboy.set_memory_value(address + i, byte) - i += 1 - - def set_text(self, text, address): - """Sets text at address. - - Will always add a string terminator (80) at the end. - """ - i = 0 - for character in text: - try: - self.pyboy.set_memory_value(address + i, get_character_index(character)) - i += 1 - except: - pass - self.pyboy.set_memory_value(address + i, constants.STRING_TERMINATOR) - - def set_rom_text(self, text, bank, address): - i = 0 - for character in text: - try: - self.pyboy.override_memory_value(bank, address + i, get_character_index(character)) - i += 1 - except: - pass - - def set_player_name(self, name): - """ - Sets the player name. - - Args: - name (string): Name to be set (will be trimmed at 8 characters). - """ - self.set_text(name[:8], 0xD158) - - def get_player_name(self): - """ - Returns player name. - """ - return self.get_text(0xD158) - - def set_rival_name(self, name): - """ - Sets the rival name. - - Args: - name (string): Name to be set (will be trimmed at 8 characters). - """ - self.set_text(name[:8], 0xD34A) - - def get_rival_name(self): - """ - Returns rival name. - """ - return self.get_text(0xD34A) - - def get_text(self, address, cap = 16): - """ - Retrieves a string from a given address. - - Args: - address (int): Address from where to retrieve text from. - cap (int): Maximum expected length of string (default: 16). - """ - i = 0 - text = '' - while i < cap: - value = self.pyboy.get_memory_value(address + i) - try: - text += chr(value - constants.ASCII_DELTA) - except: - pass - if value == constants.STRING_TERMINATOR: - break - i += 1 - return text - - def set_palette_to_darkness(self): - self.pyboy.set_memory_value(0xD35D, 6) - - def set_player_monster(self, index, monster): - """ - Sets player monster at a given index. - - Args: - index (int): Which monster to change (0-5). - monster (int): Which type of monster to set. - """ - self.pyboy.set_memory_value(0xD16B + index, monster) - self.pyboy.set_memory_value(0xD164 + (index * PKMN_SIZE), monster) - - def get_player_monster(self, index): - """ - Returns player monster at a given index. - - Args: - index (int): Which monster to change (0-5). - """ - return self.pyboy.get_memory_value(0xD16B + index) - - def set_player_monster_nickname(self, index, text): - """ - Sets player monster's nickname at a given index. - - Args: - index (int): Which monster to change (0-5). - text (string): Nickname to set (will be trimmed at 10 characters). - """ - self.set_text(text[:10], 0xD2B5 + (index * PKMN_SIZE)) - - def get_player_monster_nickname(self, index): - """ - Returns player monster's nickname at a given index. - - Args: - index (int): Which monster (0-5). - """ - return self.get_text(0xD2B5 + (index * PKMN_SIZE)) - - def set_player_monster_move(self, index, move_index, move): - """ - Sets player monster's move at a given index. - - Args: - index (int): Which monster to change (0-5). - move_index (int): Which move to change (0-3). - move (int): Which type of move to set. - """ - self.pyboy.set_memory_value(0xD01C + (index * PKMN_SIZE) + move_index, move) - - def get_player_monster_move(self, index, move_index): - """ - Returns player monster's move at a given index. - - Args: - index (int): Which monster (0-5). - move_index (int): Which move to change (0-3). - """ - return self.pyboy.get_memory_value(0xD01C + (index * PKMN_SIZE) + move_index) - - def get_player_monster_current_hp(self, index): - """ - Returns player monster's current HP at a given index. - - Args: - index (int): Which monster (0-5). - """ - return self.get_int_at_address(0xD16C + (index * PKMN_SIZE)) - - def get_active_player_monster_current_hp(self): - return self.get_int_at_address(0xD015) - - def set_player_monster_current_hp(self, index, hp): - """ - Sets the current HP of a given player monster. - - Args: - index (int): Which monster to change (0-5). - hp (int): Health points. - """ - self.set_int_at_address(0xD16C + (index * PKMN_SIZE), hp) - - def set_active_player_monster_current_hp(self, hp): - self.set_int_at_address(0xD015, hp) - - def get_player_monster_max_hp(self, index): - """ - Returns player monster's max HP at a given index. - - Args: - index (int): Which monster (0-5). - """ - return self.get_int_at_address(0xD18D + (index * PKMN_SIZE)) - - def get_active_player_monster_max_hp(self): - return self.get_int_at_address(0xD023) - - def set_player_monster_max_hp(self, index, hp): - """ - Sets the max HP of a given player monster. - - Args: - index (int): Which monster to change (0-5). - hp (int): Health points. - """ - self.set_int_at_address(0xD18D + (index * PKMN_SIZE), hp) - - def set_active_player_monster_max_hp(self, hp): - return self.set_int_at_address(0xD023, hp) - - def set_player_monster_status(self, index, status): - """ - Sets the ailment status of a given player monster. - - Args: - index (int): Which monster to change (0-5). - status (int): Status to be set. - """ - assert status >= 0 and status < 0xFF - assert index < 6 - self.pyboy.set_memory_value(0xD16F + (index * PKMN_SIZE), status) - - def set_player_monster_asleep(self, index): - self.set_player_monster_status(index, constants.STATUS_ASLEEP) - - def set_player_monster_poisoned(self, index): - self.set_player_monster_status(index, constants.STATUS_POISONED) - - def set_player_monster_burned(self, index): - self.set_player_monster_status(index, constants.STATUS_BURNED) - - def set_player_monster_frozen(self, index): - self.set_player_monster_status(index, constants.STATUS_FROZEN) - - def set_player_monster_paralyzed(self, index): - self.set_player_monster_status(index, constants.STATUS_PARALYZED) - - def set_player_monster_no_ailment(self, index): - self.set_player_monster_status(index, 0) - - def get_player_money(self): - return self.get_int_at_address(0xD347, size=3) - - def set_active_player_monster_status(self, status): - self.pyboy.set_memory_value(0xD018, status) - - def set_active_player_monster_asleep(self): - self.set_active_player_monster_status(constants.STATUS_ASLEEP) - - def set_active_player_monster_poisoned(self): - self.set_active_player_monster_status(constants.STATUS_POISONED) - - def set_active_player_monster_burned(self): - self.set_active_player_monster_status(constants.STATUS_BURNED) - - def set_active_player_monster_frozen(self): - self.set_active_player_monster_status(constants.STATUS_FROZEN) - - def set_active_player_monster_paralyzed(self): - self.set_active_player_monster_status(constants.STATUS_PARALYZED) - - def set_active_player_monster_no_ailment(self): - self.set_active_player_monster_status(0) - - def set_active_player_monster_move(self, index, move): - self.pyboy.set_memory_value(0xD01C + index, move) - - def set_active_opponent_monster_move(self, index, move): - self.pyboy.set_memory_value(0xCFED + index, move) - - def set_active_player_monster_nickname(self, nickname): - self.set_text(nickname[:10], 0xD009) - - def set_active_opponent_monster_nickname(self, nickname): - self.set_text(nickname[:10], 0xCFDA) - - def set_active_opponent_monster_status(self, status): - self.pyboy.set_memory_value(0xCFE9, status) - - def set_active_opponent_monster_asleep(self): - self.set_active_opponent_monster_status(constants.STATUS_ASLEEP) - - def set_active_opponent_monster_poisoned(self): - self.set_active_opponent_monster_status(constants.STATUS_POISONED) - - def set_active_opponent_monster_burned(self): - self.set_active_opponent_monster_status(constants.STATUS_BURNED) - - def set_active_opponent_monster_frozen(self): - self.set_active_opponent_monster_status(constants.STATUS_FROZEN) - - def set_active_opponent_monster_paralyzed(self): - self.set_active_opponent_monster_status(constants.STATUS_PARALYZED) - - def set_active_opponent_monster_no_ailment(self): - self.set_active_opponent_monster_status(0) - - def heal_player_monster(self, index): - """ - Fully heals a player monster. - - Args: - index (int): Which monster to change (0-5). - """ - self.set_player_monster_no_ailment(index) - max_hp = self.get_player_monster_max_hp(index) - self.set_player_monster_current_hp(index, max_hp) - - def heal_active_player_monster(self): - self.set_active_player_monster_no_ailment() - max_hp = self.get_active_player_monster_max_hp() - self.set_active_player_monster_current_hp(max_hp) - - def is_battle_happening(self): - return self.pyboy.get_memory_value(0xD057) != 0 - - def get_current_map(self): - return self.pyboy.get_memory_value(0xD35E) - - def get_current_map_name(self): - return constants.MAP_NAMES[self.get_current_map()] - - def set_wild_encounter_rate(self, value): - self.pyboy.set_memory_value(0xD887, value) - - # TODO: Add player position functions From 6e41541f919ed1e2e23da717ba850358c84a35fc Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Fri, 3 Nov 2023 19:36:53 -0400 Subject: [PATCH 05/74] Add debug.pxi --- pyboy/core/debug.pxi | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 pyboy/core/debug.pxi diff --git a/pyboy/core/debug.pxi b/pyboy/core/debug.pxi new file mode 100644 index 000000000..6d91d73d9 --- /dev/null +++ b/pyboy/core/debug.pxi @@ -0,0 +1,5 @@ +# +# License: See LICENSE.md file +# GitHub: https://github.com/Baekalfen/PyBoy +# +DEF DEBUG=0 From a52ec6cdf8690834584fddf5c0b3944ee1c5d69a Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Sat, 4 Nov 2023 15:38:12 -0400 Subject: [PATCH 06/74] Add functions to read/write multiple consecutive bytes of memory --- pyboy/pyboy.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/pyboy/pyboy.py b/pyboy/pyboy.py index 40a2f597b..adc36336d 100644 --- a/pyboy/pyboy.py +++ b/pyboy/pyboy.py @@ -322,6 +322,22 @@ def get_memory_value(self, addr): An integer with the value of the memory address """ return self.mb.getitem(addr) + + def get_consecutive_memory_values(self, addr, num_bytes, byte_order='big'): + """ + Reads anum_bytes consecutive memory addresses of the Game Boy's current memory state. This will not directly give you access to + all switchable memory banks. Open an issue on GitHub if that is needed, or use `PyBoy.set_memory_value` to send + MBC commands to the virtual cartridge. + + Returns + ------- + int: + An integer with the value of the memory addresses in byte_order endian format + """ + bytes = [] + for i in range(num_bytes): + bytes.append(self.get_memory_value(addr + i)) + return int.from_bytes(bytes, byteorder=byte_order) def set_memory_value(self, addr, value): """ @@ -341,6 +357,26 @@ def set_memory_value(self, addr, value): """ self.mb.setitem(addr, value) + def set_consecutive_memory_values(self, addr, value, num_bytes, byte_order='big'): + """ + Write consecutive bytes starting at a given memory address of the Game Boy's current memory state. + + This will not directly give you access to all switchable memory banks. + + __NOTE:__ This function will not let you change ROM addresses (0x0000 to 0x8000). If you write to these + addresses, it will send commands to the "Memory Bank Controller" (MBC) of the virtual cartridge. You can read + about the MBC at [Pan Docs](http://bgb.bircd.org/pandocs.htm). + + If you need to change ROM values, see `pyboy.PyBoy.override_memory_value`. + + Args: + addr (int): Address to write the byte + value (int): A byte of data + """ + bytes = value.to_bytes(num_bytes, byteorder=self.byte_order) + for i, byte in enumerate(bytes): + self.pyboy.set_memory_value(addr + i, byte) + def override_memory_value(self, rom_bank, addr, value): """ Override one byte at a given memory address of the Game Boy's ROM. From 2b591d35ff8e58239ba35d07350b0c5d9cedf924 Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Sat, 4 Nov 2023 15:39:35 -0400 Subject: [PATCH 07/74] Create Python file with memory addresses so they can be referenced as human-readable enums rather than raw hex values --- .../game_wrapper_pokemon_gen1/memory.py | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 pyboy/plugins/game_wrapper_pokemon_gen1/memory.py diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/memory.py b/pyboy/plugins/game_wrapper_pokemon_gen1/memory.py new file mode 100644 index 000000000..5119ceb6e --- /dev/null +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/memory.py @@ -0,0 +1,32 @@ +from enum import Enum + +# All info from https://datacrystal.romhacking.net/wiki/Pok%C3%A9mon_Red/Blue:RAM_map#ROM_banking + +class PokemonMemAddrs(Enum): + POKEMON_1 = 0xD16B + POKEMON_2 = 0xD197 + POKEMON_3 = 0xD1C3 + POKEMON_4 = 0xD1EF + POKEMON_5 = 0xD21B + POKEMON_6 = 0xD247 + +class PokemonMemOffs(Enum): + POKEMON = (0x0, 1) + CURRENT_HP = (0x1, 2) + STATUS = (0x3, 1) + TYPE_1 = (0x4, 1) + TYPE_2 = (0x5, 1) + CATCH_RATE = (0x6, 1) + MOVE_1 = (0x7, 1) + MOVE_2 = (0x8, 1) + MOVE_3 = (0x9, 1) + MOVE_4 = (0xA, 1) + TRAINER_ID = (0xB, 2) + EXPERIENCE = (0xD, 3) + +class PokemonMemoryWriter: + + def __init__(self, byte_order='big'): + self.byte_order = byte_order + + \ No newline at end of file From b63f66b07092e436828ed5cc52e25f9411f1dfd6 Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Sat, 4 Nov 2023 17:45:17 -0400 Subject: [PATCH 08/74] Convert get_memory_value and set_memory_value to allow for reading and writing multiple bytes simultaniously, with the default length being 1 --- pyboy/pyboy.py | 30 ++++++------------------------ 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/pyboy/pyboy.py b/pyboy/pyboy.py index adc36336d..0ebca532c 100644 --- a/pyboy/pyboy.py +++ b/pyboy/pyboy.py @@ -323,9 +323,9 @@ def get_memory_value(self, addr): """ return self.mb.getitem(addr) - def get_consecutive_memory_values(self, addr, num_bytes, byte_order='big'): + def get_memory_value(self, addr, num_bytes=1, byte_order='big'): """ - Reads anum_bytes consecutive memory addresses of the Game Boy's current memory state. This will not directly give you access to + Reads num_bytes consecutive memory addresses of the Game Boy's current memory state. This will not directly give you access to all switchable memory banks. Open an issue on GitHub if that is needed, or use `PyBoy.set_memory_value` to send MBC commands to the virtual cartridge. @@ -336,28 +336,10 @@ def get_consecutive_memory_values(self, addr, num_bytes, byte_order='big'): """ bytes = [] for i in range(num_bytes): - bytes.append(self.get_memory_value(addr + i)) + bytes.append(self.mb.getitem(addr + i)) return int.from_bytes(bytes, byteorder=byte_order) - def set_memory_value(self, addr, value): - """ - Write one byte to a given memory address of the Game Boy's current memory state. - - This will not directly give you access to all switchable memory banks. - - __NOTE:__ This function will not let you change ROM addresses (0x0000 to 0x8000). If you write to these - addresses, it will send commands to the "Memory Bank Controller" (MBC) of the virtual cartridge. You can read - about the MBC at [Pan Docs](http://bgb.bircd.org/pandocs.htm). - - If you need to change ROM values, see `pyboy.PyBoy.override_memory_value`. - - Args: - addr (int): Address to write the byte - value (int): A byte of data - """ - self.mb.setitem(addr, value) - - def set_consecutive_memory_values(self, addr, value, num_bytes, byte_order='big'): + def set_memory_value(self, addr, value, num_bytes=1, byte_order='big'): """ Write consecutive bytes starting at a given memory address of the Game Boy's current memory state. @@ -373,9 +355,9 @@ def set_consecutive_memory_values(self, addr, value, num_bytes, byte_order='big' addr (int): Address to write the byte value (int): A byte of data """ - bytes = value.to_bytes(num_bytes, byteorder=self.byte_order) + bytes = value.to_bytes(num_bytes, byteorder=byte_order) for i, byte in enumerate(bytes): - self.pyboy.set_memory_value(addr + i, byte) + self.mb.setitem(addr + i, byte) def override_memory_value(self, rom_bank, addr, value): """ From c6dc375ec74c9092e6226472bab2403279276260 Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Sat, 4 Nov 2023 17:48:36 -0400 Subject: [PATCH 09/74] Create Gen1MemoryManager, a class to wrap memory read/writes for Pokemon Red/Blue so that data can be interacted with in a more Pythonic way --- .../game_wrapper_pokemon_gen1.pxd | 3 +- .../game_wrapper_pokemon_gen1.py | 21 ++-------- .../gen_1_memory_manager.pxd | 11 +++++ .../gen_1_memory_manager.py | 41 +++++++++++++++++++ .../game_wrapper_pokemon_gen1/memory.py | 32 --------------- 5 files changed, 58 insertions(+), 50 deletions(-) create mode 100644 pyboy/plugins/game_wrapper_pokemon_gen1/gen_1_memory_manager.pxd create mode 100644 pyboy/plugins/game_wrapper_pokemon_gen1/gen_1_memory_manager.py delete mode 100644 pyboy/plugins/game_wrapper_pokemon_gen1/memory.py diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.pxd b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.pxd index 499f68737..41bd6bdb1 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.pxd +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.pxd @@ -4,7 +4,8 @@ # from libc.stdint cimport uint8_t from pyboy.plugins.base_plugin cimport PyBoyGameWrapper +from pyboy.plugins.game_wrapper_pokemon_gen1.gen_1_memory_manager cimport Gen1MemoryManager cimport cython cdef class GameWrapperPokemonGen1(PyBoyGameWrapper): - pass \ No newline at end of file + cdef Gen1MemoryManager memory_manager \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py index 59831a3f3..8276f1ac9 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py @@ -12,6 +12,7 @@ from pyboy.utils import WindowEvent from pyboy.logger import logger from ..base_plugin import PyBoyGameWrapper +from .gen_1_memory_manager import Gen1MemoryManager from . import constants from .utils import get_character_index @@ -28,7 +29,7 @@ class GameWrapperPokemonGen1(PyBoyGameWrapper): """ - This class wraps Pokemon Red, and provides easy access to score and a "fitness" score for AIs. + This class wraps Pokemon Red/Blue. If you call `print` on an instance of this object, it will show an overview of everything this object provides. """ @@ -37,6 +38,7 @@ class GameWrapperPokemonGen1(PyBoyGameWrapper): def __init__(self, *args, **kwargs): self.shape = (20, 18) super().__init__(*args, game_area_section=(0, 0) + self.shape, game_area_wrap_around=True, **kwargs) + self.memory_manager = Gen1MemoryManager(self.pyboy) def enabled(self): return self.pyboy_argv.get("game_wrapper") and ((self.pyboy.cartridge_title() == "POKEMON RED") or @@ -109,21 +111,6 @@ def __repr__(self): ) # yapf: enable - def get_int_at_address(self, address, size=2): - """Returns an integer from a given address of a specified size.""" - bytes = [] - for i in range(size): - bytes.append(self.pyboy.get_memory_value(address + i)) - return int.from_bytes(bytes, byteorder=BYTE_ORDER) - - def set_int_at_address(self, address, value, size=2): - """Sets an integer at a given address of a specified size.""" - bytes = value.to_bytes(2, byteorder=BYTE_ORDER) - i = 0 - for byte in bytes: - self.pyboy.set_memory_value(address + i, byte) - i += 1 - def set_text(self, text, address): """Sets text at address. @@ -219,7 +206,7 @@ def get_player_monster(self, index): Args: index (int): Which monster to change (0-5). """ - return self.pyboy.get_memory_value(0xD16B + index) + return self.memory_manager.get_pokemon_1_info() def set_player_monster_nickname(self, index, text): """ diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/gen_1_memory_manager.pxd b/pyboy/plugins/game_wrapper_pokemon_gen1/gen_1_memory_manager.pxd new file mode 100644 index 000000000..91f9048c5 --- /dev/null +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/gen_1_memory_manager.pxd @@ -0,0 +1,11 @@ +# +# License: See LICENSE.md file +# GitHub: https://github.com/Baekalfen/PyBoy +# +from libc.stdint cimport uint8_t +from pyboy.pyboy cimport PyBoy +cimport cython + +cdef class Gen1MemoryManager: + cdef PyBoy pyboy + cdef str byte_order \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/gen_1_memory_manager.py b/pyboy/plugins/game_wrapper_pokemon_gen1/gen_1_memory_manager.py new file mode 100644 index 000000000..1e9981b00 --- /dev/null +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/gen_1_memory_manager.py @@ -0,0 +1,41 @@ +from enum import Enum + +# All info from https://datacrystal.romhacking.net/wiki/Pok%C3%A9mon_Red/Blue:RAM_map#ROM_banking + +SRAM = (0xA000, 0xBFFF) +WRAM = (0xC000, 0xDFFF) # Unsure of where this range ACTUALLY ends +HRAM = (0xFF80, 0xFFFE) + +# Pokemon locations in memory +POKEMON_1_BASE = 0xD16B +POKEMON_2_BASE = 0xD197 +POKEMON_3_BASE = 0xD1C3 +POKEMON_4_BASE = 0xD1EF +POKEMON_5_BASE = 0xD21B +POKEMON_6_BASE = 0xD247 + +# Offsets for Pokemon data access +# Structure is (offset, num bytes) +POKEMON_OFFSET = (0x0, 1) +POKEMON_CURRENT_HP_OFFSET = (0x1, 2) +POKEMON_STATUS_OFFSET = (0x3, 1) +POKEMON_TYPE_1_OFFSET = (0x4, 1) +POKEMON_TYPE_2_OFFSET = (0x5, 1) +POKEMON_CATCH_RATE_OFFSET = (0x6, 1) +POKEMON_MOVE_1_OFFSET = (0x7, 1) +POKEMON_MOVE_2_OFFSET = (0x8, 1) +POKEMON_MOVE_3_OFFSET = (0x9, 1) +POKEMON_MOVE_4_OFFSET = (0xA, 1) +POKEMON_TRAINER_ID_OFFSET = (0xB, 2) +POKEMON_EXPERIENCE_OFFSET = (0xD, 3) + +POKEMON_LEVEL_OFFSET = (0x21, 1) + +class Gen1MemoryManager: + + def __init__(self, pyboy, byte_order='big'): + self.pyboy = pyboy + self.byte_order = byte_order + + def get_pokemon_1_info(self): + return self.pyboy.get_memory_value(POKEMON_1_BASE + LEVEL[0]) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/memory.py b/pyboy/plugins/game_wrapper_pokemon_gen1/memory.py deleted file mode 100644 index 5119ceb6e..000000000 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/memory.py +++ /dev/null @@ -1,32 +0,0 @@ -from enum import Enum - -# All info from https://datacrystal.romhacking.net/wiki/Pok%C3%A9mon_Red/Blue:RAM_map#ROM_banking - -class PokemonMemAddrs(Enum): - POKEMON_1 = 0xD16B - POKEMON_2 = 0xD197 - POKEMON_3 = 0xD1C3 - POKEMON_4 = 0xD1EF - POKEMON_5 = 0xD21B - POKEMON_6 = 0xD247 - -class PokemonMemOffs(Enum): - POKEMON = (0x0, 1) - CURRENT_HP = (0x1, 2) - STATUS = (0x3, 1) - TYPE_1 = (0x4, 1) - TYPE_2 = (0x5, 1) - CATCH_RATE = (0x6, 1) - MOVE_1 = (0x7, 1) - MOVE_2 = (0x8, 1) - MOVE_3 = (0x9, 1) - MOVE_4 = (0xA, 1) - TRAINER_ID = (0xB, 2) - EXPERIENCE = (0xD, 3) - -class PokemonMemoryWriter: - - def __init__(self, byte_order='big'): - self.byte_order = byte_order - - \ No newline at end of file From 1815652e357902cc23d0299df8633ca6ee2d69de Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Sat, 4 Nov 2023 17:57:43 -0400 Subject: [PATCH 10/74] Convert moves to an Enum --- .../game_wrapper_pokemon_gen1/constants.py | 332 +++++++++--------- 1 file changed, 167 insertions(+), 165 deletions(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py b/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py index 4e857a32f..3e1f61ee2 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py @@ -1,171 +1,173 @@ +from enum import Enum + STRING_TERMINATOR = 80 ASCII_DELTA = 63 -# Moves -MOVE_POUND = 0x01 -MOVE_KARATE_CHOP = 0x02 -MOVE_DOUBLESLAP = 0x03 -MOVE_COMET_PUNCH = 0x04 -MOVE_MEGA_PUNCH = 0x05 -MOVE_PAY_DAY = 0x06 -MOVE_FIRE_PUNCH = 0x07 -MOVE_ICE_PUNCH = 0x08 -MOVE_THUNDERPUNCH = 0x09 -MOVE_SCRATCH = 0x0a -MOVE_VICEGRIP = 0x0b -MOVE_GUILLOTINE = 0x0c -MOVE_RAZOR_WIND = 0x0d -MOVE_SWORDS_DANCE = 0x0e -MOVE_CUT = 0x0f -MOVE_GUST = 0x10 -MOVE_WING_ATTACK = 0x11 -MOVE_WHIRLWIND = 0x12 -MOVE_FLY = 0x13 -MOVE_BIND = 0x14 -MOVE_SLAM = 0x15 -MOVE_VINE_WHIP = 0x16 -MOVE_STOMP = 0x17 -MOVE_DOUBLE_KICK = 0x18 -MOVE_MEGA_KICK = 0x19 -MOVE_JUMP_KICK = 0x1a -MOVE_ROLLING_KICK = 0x1b -MOVE_SAND_ATTACK = 0x1c -MOVE_HEADBUTT = 0x1d -MOVE_HORN_ATTACK = 0x1e -MOVE_FURY_ATTACK = 0x1f -MOVE_HORN_DRILL = 0x20 -MOVE_TACKLE = 0x21 -MOVE_BODY_SLAM = 0x22 -MOVE_WRAP = 0x23 -MOVE_TAKE_DOWN = 0x24 -MOVE_THRASH = 0x25 -MOVE_DOUBLE_EDGE = 0x26 -MOVE_TAIL_WHIP = 0x27 -MOVE_POISON_STING = 0x28 -MOVE_TWINEEDLE = 0x29 -MOVE_PIN_MISSILE = 0x2a -MOVE_LEER = 0x2b -MOVE_BITE = 0x2c -MOVE_GROWL = 0x2d -MOVE_ROAR = 0x2e -MOVE_SING = 0x2f -MOVE_SUPERSONIC = 0x30 -MOVE_SONICBOOM = 0x31 -MOVE_DISABLE = 0x32 -MOVE_ACID = 0x33 -MOVE_EMBER = 0x34 -MOVE_FLAMETHROWER = 0x35 -MOVE_MIST = 0x36 -MOVE_WATER_GUN = 0x37 -MOVE_HYDRO_PUMP = 0x38 -MOVE_SURF = 0x39 -MOVE_ICE_BEAM = 0x3a -MOVE_BLIZZARD = 0x3b -MOVE_PSYBEAM = 0x3c -MOVE_BUBBLEBEAM = 0x3d -MOVE_AURORA_BEAM = 0x3e -MOVE_HYPER_BEAM = 0x3f -MOVE_PECK = 0x40 -MOVE_DRILL_PECK = 0x41 -MOVE_SUBMISSION = 0x42 -MOVE_LOW_KICK = 0x43 -MOVE_COUNTER = 0x44 -MOVE_SEISMIC_TOSS = 0x45 -MOVE_STRENGTH = 0x46 -MOVE_ABSORB = 0x47 -MOVE_MEGA_DRAIN = 0x48 -MOVE_LEECH_SEED = 0x49 -MOVE_GROWTH = 0x4a -MOVE_RAZOR_LEAF = 0x4b -MOVE_SOLARBEAM = 0x4c -MOVE_POISONPOWDER = 0x4d -MOVE_STUN_SPORE = 0x4e -MOVE_SLEEP_POWDER = 0x4f -MOVE_PETAL_DANCE = 0x50 -MOVE_STRING_SHOT = 0x51 -MOVE_DRAGON_RAGE = 0x52 -MOVE_FIRE_SPIN = 0x53 -MOVE_THUNDERSHOCK = 0x54 -MOVE_THUNDERBOLT = 0x55 -MOVE_THUNDER_WAVE = 0x56 -MOVE_THUNDER = 0x57 -MOVE_ROCK_THROW = 0x58 -MOVE_EARTHQUAKE = 0x59 -MOVE_FISSURE = 0x5a -MOVE_DIG = 0x5b -MOVE_TOXIC = 0x5c -MOVE_CONFUSION = 0x5d -MOVE_PSYCHIC_M = 0x5e -MOVE_HYPNOSIS = 0x5f -MOVE_MEDITATE = 0x60 -MOVE_AGILITY = 0x61 -MOVE_QUICK_ATTACK = 0x62 -MOVE_RAGE = 0x63 -MOVE_TELEPORT = 0x64 -MOVE_NIGHT_SHADE = 0x65 -MOVE_MIMIC = 0x66 -MOVE_SCREECH = 0x67 -MOVE_DOUBLE_TEAM = 0x68 -MOVE_RECOVER = 0x69 -MOVE_HARDEN = 0x6a -MOVE_MINIMIZE = 0x6b -MOVE_SMOKESCREEN = 0x6c -MOVE_CONFUSE_RAY = 0x6d -MOVE_WITHDRAW = 0x6e -MOVE_DEFENSE_CURL = 0x6f -MOVE_BARRIER = 0x70 -MOVE_LIGHT_SCREEN = 0x71 -MOVE_HAZE = 0x72 -MOVE_REFLECT = 0x73 -MOVE_FOCUS_ENERGY = 0x74 -MOVE_BIDE = 0x75 -MOVE_METRONOME = 0x76 -MOVE_MIRROR_MOVE = 0x77 -MOVE_SELFDESTRUCT = 0x78 -MOVE_EGG_BOMB = 0x79 -MOVE_LICK = 0x7a -MOVE_SMOG = 0x7b -MOVE_SLUDGE = 0x7c -MOVE_BONE_CLUB = 0x7d -MOVE_FIRE_BLAST = 0x7e -MOVE_WATERFALL = 0x7f -MOVE_CLAMP = 0x80 -MOVE_SWIFT = 0x81 -MOVE_SKULL_BASH = 0x82 -MOVE_SPIKE_CANNON = 0x83 -MOVE_CONSTRICT = 0x84 -MOVE_AMNESIA = 0x85 -MOVE_KINESIS = 0x86 -MOVE_SOFTBOILED = 0x87 -MOVE_HI_JUMP_KICK = 0x88 -MOVE_GLARE = 0x89 -MOVE_DREAM_EATER = 0x8a -MOVE_POISON_GAS = 0x8b -MOVE_BARRAGE = 0x8c -MOVE_LEECH_LIFE = 0x8d -MOVE_LOVELY_KISS = 0x8e -MOVE_SKY_ATTACK = 0x8f -MOVE_TRANSFORM = 0x90 -MOVE_BUBBLE = 0x91 -MOVE_DIZZY_PUNCH = 0x92 -MOVE_SPORE = 0x93 -MOVE_FLASH = 0x94 -MOVE_PSYWAVE = 0x95 -MOVE_SPLASH = 0x96 -MOVE_ACID_ARMOR = 0x97 -MOVE_CRABHAMMER = 0x98 -MOVE_EXPLOSION = 0x99 -MOVE_FURY_SWIPES = 0x9a -MOVE_BONEMERANG = 0x9b -MOVE_REST = 0x9c -MOVE_ROCK_SLIDE = 0x9d -MOVE_HYPER_FANG = 0x9e -MOVE_SHARPEN = 0x9f -MOVE_CONVERSION = 0xa0 -MOVE_TRI_ATTACK = 0xa1 -MOVE_SUPER_FANG = 0xa2 -MOVE_SLASH = 0xa3 -MOVE_SUBSTITUTE = 0xa4 +class Moves(Enum): + POUND = 0x01 + KARATE_CHOP = 0x02 + DOUBLESLAP = 0x03 + COMET_PUNCH = 0x04 + MEGA_PUNCH = 0x05 + PAY_DAY = 0x06 + FIRE_PUNCH = 0x07 + ICE_PUNCH = 0x08 + THUNDERPUNCH = 0x09 + SCRATCH = 0x0a + VICEGRIP = 0x0b + GUILLOTINE = 0x0c + RAZOR_WIND = 0x0d + SWORDS_DANCE = 0x0e + CUT = 0x0f + GUST = 0x10 + WING_ATTACK = 0x11 + WHIRLWIND = 0x12 + FLY = 0x13 + BIND = 0x14 + SLAM = 0x15 + VINE_WHIP = 0x16 + STOMP = 0x17 + DOUBLE_KICK = 0x18 + MEGA_KICK = 0x19 + JUMP_KICK = 0x1a + ROLLING_KICK = 0x1b + SAND_ATTACK = 0x1c + HEADBUTT = 0x1d + HORN_ATTACK = 0x1e + FURY_ATTACK = 0x1f + HORN_DRILL = 0x20 + TACKLE = 0x21 + BODY_SLAM = 0x22 + WRAP = 0x23 + TAKE_DOWN = 0x24 + THRASH = 0x25 + DOUBLE_EDGE = 0x26 + TAIL_WHIP = 0x27 + POISON_STING = 0x28 + TWINEEDLE = 0x29 + PIN_MISSILE = 0x2a + LEER = 0x2b + BITE = 0x2c + GROWL = 0x2d + ROAR = 0x2e + SING = 0x2f + SUPERSONIC = 0x30 + SONICBOOM = 0x31 + DISABLE = 0x32 + ACID = 0x33 + EMBER = 0x34 + FLAMETHROWER = 0x35 + MIST = 0x36 + WATER_GUN = 0x37 + HYDRO_PUMP = 0x38 + SURF = 0x39 + ICE_BEAM = 0x3a + BLIZZARD = 0x3b + PSYBEAM = 0x3c + BUBBLEBEAM = 0x3d + AURORA_BEAM = 0x3e + HYPER_BEAM = 0x3f + PECK = 0x40 + DRILL_PECK = 0x41 + SUBMISSION = 0x42 + LOW_KICK = 0x43 + COUNTER = 0x44 + SEISMIC_TOSS = 0x45 + STRENGTH = 0x46 + ABSORB = 0x47 + MEGA_DRAIN = 0x48 + LEECH_SEED = 0x49 + GROWTH = 0x4a + RAZOR_LEAF = 0x4b + SOLARBEAM = 0x4c + POISONPOWDER = 0x4d + STUN_SPORE = 0x4e + SLEEP_POWDER = 0x4f + PETAL_DANCE = 0x50 + STRING_SHOT = 0x51 + DRAGON_RAGE = 0x52 + FIRE_SPIN = 0x53 + THUNDERSHOCK = 0x54 + THUNDERBOLT = 0x55 + THUNDER_WAVE = 0x56 + THUNDER = 0x57 + ROCK_THROW = 0x58 + EARTHQUAKE = 0x59 + FISSURE = 0x5a + DIG = 0x5b + TOXIC = 0x5c + CONFUSION = 0x5d + PSYCHIC_M = 0x5e + HYPNOSIS = 0x5f + MEDITATE = 0x60 + AGILITY = 0x61 + QUICK_ATTACK = 0x62 + RAGE = 0x63 + TELEPORT = 0x64 + NIGHT_SHADE = 0x65 + MIMIC = 0x66 + SCREECH = 0x67 + DOUBLE_TEAM = 0x68 + RECOVER = 0x69 + HARDEN = 0x6a + MINIMIZE = 0x6b + SMOKESCREEN = 0x6c + CONFUSE_RAY = 0x6d + WITHDRAW = 0x6e + DEFENSE_CURL = 0x6f + BARRIER = 0x70 + LIGHT_SCREEN = 0x71 + HAZE = 0x72 + REFLECT = 0x73 + FOCUS_ENERGY = 0x74 + BIDE = 0x75 + METRONOME = 0x76 + MIRROR_MOVE = 0x77 + SELFDESTRUCT = 0x78 + EGG_BOMB = 0x79 + LICK = 0x7a + SMOG = 0x7b + SLUDGE = 0x7c + BONE_CLUB = 0x7d + FIRE_BLAST = 0x7e + WATERFALL = 0x7f + CLAMP = 0x80 + SWIFT = 0x81 + SKULL_BASH = 0x82 + SPIKE_CANNON = 0x83 + CONSTRICT = 0x84 + AMNESIA = 0x85 + KINESIS = 0x86 + SOFTBOILED = 0x87 + HI_JUMP_KICK = 0x88 + GLARE = 0x89 + DREAM_EATER = 0x8a + POISON_GAS = 0x8b + BARRAGE = 0x8c + LEECH_LIFE = 0x8d + LOVELY_KISS = 0x8e + SKY_ATTACK = 0x8f + TRANSFORM = 0x90 + BUBBLE = 0x91 + DIZZY_PUNCH = 0x92 + SPORE = 0x93 + FLASH = 0x94 + PSYWAVE = 0x95 + SPLASH = 0x96 + ACID_ARMOR = 0x97 + CRABHAMMER = 0x98 + EXPLOSION = 0x99 + FURY_SWIPES = 0x9a + BONEMERANG = 0x9b + REST = 0x9c + ROCK_SLIDE = 0x9d + HYPER_FANG = 0x9e + SHARPEN = 0x9f + CONVERSION = 0xa0 + TRI_ATTACK = 0xa1 + SUPER_FANG = 0xa2 + SLASH = 0xa3 + SUBSTITUTE = 0xa4 MONSTER_RHYDON = 0x01 MONSTER_KANGASKHAN = 0x02 From 1f518c0585dccc2de4b24ae83eccd239b1ca07f9 Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Sat, 4 Nov 2023 18:05:35 -0400 Subject: [PATCH 11/74] Convert Pokemon (previously MONSTERS) into Enum --- .../game_wrapper_pokemon_gen1/constants.py | 383 +++++++++--------- 1 file changed, 192 insertions(+), 191 deletions(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py b/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py index 3e1f61ee2..be91704bb 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py @@ -169,196 +169,197 @@ class Moves(Enum): SLASH = 0xa3 SUBSTITUTE = 0xa4 -MONSTER_RHYDON = 0x01 -MONSTER_KANGASKHAN = 0x02 -MONSTER_NIDORAN_M = 0x03 -MONSTER_CLEFAIRY = 0x04 -MONSTER_SPEAROW = 0x05 -MONSTER_VOLTORB = 0x06 -MONSTER_NIDOKING = 0x07 -MONSTER_SLOWBRO = 0x08 -MONSTER_IVYSAUR = 0x09 -MONSTER_EXEGGUTOR = 0x0A -MONSTER_LICKITUNG = 0x0B -MONSTER_EXEGGCUTE = 0x0C -MONSTER_GRIMER = 0x0D -MONSTER_GENGAR = 0x0E -MONSTER_NIDORAN_F = 0x0F -MONSTER_NIDOQUEEN = 0x10 -MONSTER_CUBONE = 0x11 -MONSTER_RHYHORN = 0x12 -MONSTER_LAPRAS = 0x13 -MONSTER_ARCANINE = 0x14 -MONSTER_MEW = 0x15 -MONSTER_GYARADOS = 0x16 -MONSTER_SHELLDER = 0x17 -MONSTER_TENTACOOL = 0x18 -MONSTER_GASTLY = 0x19 -MONSTER_SCYTHER = 0x1A -MONSTER_STARYU = 0x1B -MONSTER_BLASTOISE = 0x1C -MONSTER_PINSIR = 0x1D -MONSTER_TANGELA = 0x1E -MONSTER_MISSINGNO_1F = 0x1F -MONSTER_MISSINGNO_20 = 0x20 -MONSTER_GROWLITHE = 0x21 -MONSTER_ONIX = 0x22 -MONSTER_FEAROW = 0x23 -MONSTER_PIDGEY = 0x24 -MONSTER_SLOWPOKE = 0x25 -MONSTER_KADABRA = 0x26 -MONSTER_GRAVELER = 0x27 -MONSTER_CHANSEY = 0x28 -MONSTER_MACHOKE = 0x29 -MONSTER_MR_MIME = 0x2A -MONSTER_HITMONLEE = 0x2B -MONSTER_HITMONCHAN = 0x2C -MONSTER_ARBOK = 0x2D -MONSTER_PARASECT = 0x2E -MONSTER_PSYDUCK = 0x2F -MONSTER_DROWZEE = 0x30 -MONSTER_GOLEM = 0x31 -MONSTER_MISSINGNO_32 = 0x32 -MONSTER_MAGMAR = 0x33 -MONSTER_MISSINGNO_34 = 0x34 -MONSTER_ELECTABUZZ = 0x35 -MONSTER_MAGNETON = 0x36 -MONSTER_KOFFING = 0x37 -MONSTER_MISSINGNO_38 = 0x38 -MONSTER_MANKEY = 0x39 -MONSTER_SEEL = 0x3A -MONSTER_DIGLETT = 0x3B -MONSTER_TAUROS = 0x3C -MONSTER_MISSINGNO_3D = 0x3D -MONSTER_MISSINGNO_3E = 0x3E -MONSTER_MISSINGNO_3F = 0x3F -MONSTER_FARFETCHD = 0x40 -MONSTER_VENONAT = 0x41 -MONSTER_DRAGONITE = 0x42 -MONSTER_MISSINGNO_43 = 0x43 -MONSTER_MISSINGNO_44 = 0x44 -MONSTER_MISSINGNO_45 = 0x45 -MONSTER_DODUO = 0x46 -MONSTER_POLIWAG = 0x47 -MONSTER_JYNX = 0x48 -MONSTER_MOLTRES = 0x49 -MONSTER_ARTICUNO = 0x4A -MONSTER_ZAPDOS = 0x4B -MONSTER_DITTO = 0x4C -MONSTER_MEOWTH = 0x4D -MONSTER_KRABBY = 0x4E -MONSTER_MISSINGNO_4F = 0x4F -MONSTER_MISSINGNO_50 = 0x50 -MONSTER_MISSINGNO_51 = 0x51 -MONSTER_VULPIX = 0x52 -MONSTER_NINETALES = 0x53 -MONSTER_PIKACHU = 0x54 -MONSTER_RAICHU = 0x55 -MONSTER_MISSINGNO_56 = 0x56 -MONSTER_MISSINGNO_57 = 0x57 -MONSTER_DRATINI = 0x58 -MONSTER_DRAGONAIR = 0x59 -MONSTER_KABUTO = 0x5A -MONSTER_KABUTOPS = 0x5B -MONSTER_HORSEA = 0x5C -MONSTER_SEADRA = 0x5D -MONSTER_MISSINGNO_5E = 0x5E -MONSTER_MISSINGNO_5F = 0x5F -MONSTER_SANDSHREW = 0x60 -MONSTER_SANDSLASH = 0x61 -MONSTER_OMANYTE = 0x62 -MONSTER_OMASTAR = 0x63 -MONSTER_JIGGLYPUFF = 0x64 -MONSTER_WIGGLYTUFF = 0x65 -MONSTER_EEVEE = 0x66 -MONSTER_FLAREON = 0x67 -MONSTER_JOLTEON = 0x68 -MONSTER_VAPOREON = 0x69 -MONSTER_MACHOP = 0x6A -MONSTER_ZUBAT = 0x6B -MONSTER_EKANS = 0x6C -MONSTER_PARAS = 0x6D -MONSTER_POLIWHIRL = 0x6E -MONSTER_POLIWRATH = 0x6F -MONSTER_WEEDLE = 0x70 -MONSTER_KAKUNA = 0x71 -MONSTER_BEEDRILL = 0x72 -MONSTER_MISSINGNO_73 = 0x73 -MONSTER_DODRIO = 0x74 -MONSTER_PRIMEAPE = 0x75 -MONSTER_DUGTRIO = 0x76 -MONSTER_VENOMOTH = 0x77 -MONSTER_DEWGONG = 0x78 -MONSTER_MISSINGNO_79 = 0x79 -MONSTER_MISSINGNO_7A = 0x7A -MONSTER_CATERPIE = 0x7B -MONSTER_METAPOD = 0x7C -MONSTER_BUTTERFREE = 0x7D -MONSTER_MACHAMP = 0x7E -MONSTER_MISSINGNO_7F = 0x7F -MONSTER_GOLDUCK = 0x80 -MONSTER_HYPNO = 0x81 -MONSTER_GOLBAT = 0x82 -MONSTER_MEWTWO = 0x83 -MONSTER_SNORLAX = 0x84 -MONSTER_MAGIKARP = 0x85 -MONSTER_MISSINGNO_86 = 0x86 -MONSTER_MISSINGNO_87 = 0x87 -MONSTER_MUK = 0x88 -MONSTER_MISSINGNO_89 = 0x89 -MONSTER_KINGLER = 0x8A -MONSTER_CLOYSTER = 0x8B -MONSTER_MISSINGNO_8C = 0x8C -MONSTER_ELECTRODE = 0x8D -MONSTER_CLEFABLE = 0x8E -MONSTER_WEEZING = 0x8F -MONSTER_PERSIAN = 0x90 -MONSTER_MAROWAK = 0x91 -MONSTER_MISSINGNO_92 = 0x92 -MONSTER_HAUNTER = 0x93 -MONSTER_ABRA = 0x94 -MONSTER_ALAKAZAM = 0x95 -MONSTER_PIDGEOTTO = 0x96 -MONSTER_PIDGEOT = 0x97 -MONSTER_STARMIE = 0x98 -MONSTER_BULBASAUR = 0x99 -MONSTER_VENUSAUR = 0x9A -MONSTER_TENTACRUEL = 0x9B -MONSTER_MISSINGNO_9C = 0x9C -MONSTER_GOLDEEN = 0x9D -MONSTER_SEAKING = 0x9E -MONSTER_MISSINGNO_9F = 0x9F -MONSTER_MISSINGNO_A0 = 0xA0 -MONSTER_MISSINGNO_A1 = 0xA1 -MONSTER_MISSINGNO_A2 = 0xA2 -MONSTER_PONYTA = 0xA3 -MONSTER_RAPIDASH = 0xA4 -MONSTER_RATTATA = 0xA5 -MONSTER_RATICATE = 0xA6 -MONSTER_NIDORINO = 0xA7 -MONSTER_NIDORINA = 0xA8 -MONSTER_GEODUDE = 0xA9 -MONSTER_PORYGON = 0xAA -MONSTER_AERODACTYL = 0xAB -MONSTER_MISSINGNO_AC = 0xAC -MONSTER_MAGNEMITE = 0xAD -MONSTER_MISSINGNO_AE = 0xAE -MONSTER_MISSINGNO_AF = 0xAF -MONSTER_CHARMANDER = 0xB0 -MONSTER_SQUIRTLE = 0xB1 -MONSTER_CHARMELEON = 0xB2 -MONSTER_WARTORTLE = 0xB3 -MONSTER_CHARIZARD = 0xB4 -MONSTER_MISSINGNO_B5 = 0xB5 -MONSTER_FOSSIL_KABUTOPS = 0xB6 -MONSTER_FOSSIL_AERODACTYL = 0xB7 -MONSTER_MON_GHOST = 0xB8 -MONSTER_ODDISH = 0xB9 -MONSTER_GLOOM = 0xBA -MONSTER_VILEPLUME = 0xBB -MONSTER_BELLSPROUT = 0xBC -MONSTER_WEEPINBELL = 0xBD -MONSTER_VICTREEBEL = 0xBE +class Pokemon(Enum): + RHYDON = 0x01 + KANGASKHAN = 0x02 + NIDORAN_M = 0x03 + CLEFAIRY = 0x04 + SPEAROW = 0x05 + VOLTORB = 0x06 + NIDOKING = 0x07 + SLOWBRO = 0x08 + IVYSAUR = 0x09 + EXEGGUTOR = 0x0A + LICKITUNG = 0x0B + EXEGGCUTE = 0x0C + GRIMER = 0x0D + GENGAR = 0x0E + NIDORAN_F = 0x0F + NIDOQUEEN = 0x10 + CUBONE = 0x11 + RHYHORN = 0x12 + LAPRAS = 0x13 + ARCANINE = 0x14 + MEW = 0x15 + GYARADOS = 0x16 + SHELLDER = 0x17 + TENTACOOL = 0x18 + GASTLY = 0x19 + SCYTHER = 0x1A + STARYU = 0x1B + BLASTOISE = 0x1C + PINSIR = 0x1D + TANGELA = 0x1E + MISSINGNO_1F = 0x1F + MISSINGNO_20 = 0x20 + GROWLITHE = 0x21 + ONIX = 0x22 + FEAROW = 0x23 + PIDGEY = 0x24 + SLOWPOKE = 0x25 + KADABRA = 0x26 + GRAVELER = 0x27 + CHANSEY = 0x28 + MACHOKE = 0x29 + MR_MIME = 0x2A + HITMONLEE = 0x2B + HITMONCHAN = 0x2C + ARBOK = 0x2D + PARASECT = 0x2E + PSYDUCK = 0x2F + DROWZEE = 0x30 + GOLEM = 0x31 + MISSINGNO_32 = 0x32 + MAGMAR = 0x33 + MISSINGNO_34 = 0x34 + ELECTABUZZ = 0x35 + MAGNETON = 0x36 + KOFFING = 0x37 + MISSINGNO_38 = 0x38 + MANKEY = 0x39 + SEEL = 0x3A + DIGLETT = 0x3B + TAUROS = 0x3C + MISSINGNO_3D = 0x3D + MISSINGNO_3E = 0x3E + MISSINGNO_3F = 0x3F + FARFETCHD = 0x40 + VENONAT = 0x41 + DRAGONITE = 0x42 + MISSINGNO_43 = 0x43 + MISSINGNO_44 = 0x44 + MISSINGNO_45 = 0x45 + DODUO = 0x46 + POLIWAG = 0x47 + JYNX = 0x48 + MOLTRES = 0x49 + ARTICUNO = 0x4A + ZAPDOS = 0x4B + DITTO = 0x4C + MEOWTH = 0x4D + KRABBY = 0x4E + MISSINGNO_4F = 0x4F + MISSINGNO_50 = 0x50 + MISSINGNO_51 = 0x51 + VULPIX = 0x52 + NINETALES = 0x53 + PIKACHU = 0x54 + RAICHU = 0x55 + MISSINGNO_56 = 0x56 + MISSINGNO_57 = 0x57 + DRATINI = 0x58 + DRAGONAIR = 0x59 + KABUTO = 0x5A + KABUTOPS = 0x5B + HORSEA = 0x5C + SEADRA = 0x5D + MISSINGNO_5E = 0x5E + MISSINGNO_5F = 0x5F + SANDSHREW = 0x60 + SANDSLASH = 0x61 + OMANYTE = 0x62 + OMASTAR = 0x63 + JIGGLYPUFF = 0x64 + WIGGLYTUFF = 0x65 + EEVEE = 0x66 + FLAREON = 0x67 + JOLTEON = 0x68 + VAPOREON = 0x69 + MACHOP = 0x6A + ZUBAT = 0x6B + EKANS = 0x6C + PARAS = 0x6D + POLIWHIRL = 0x6E + POLIWRATH = 0x6F + WEEDLE = 0x70 + KAKUNA = 0x71 + BEEDRILL = 0x72 + MISSINGNO_73 = 0x73 + DODRIO = 0x74 + PRIMEAPE = 0x75 + DUGTRIO = 0x76 + VENOMOTH = 0x77 + DEWGONG = 0x78 + MISSINGNO_79 = 0x79 + MISSINGNO_7A = 0x7A + CATERPIE = 0x7B + METAPOD = 0x7C + BUTTERFREE = 0x7D + MACHAMP = 0x7E + MISSINGNO_7F = 0x7F + GOLDUCK = 0x80 + HYPNO = 0x81 + GOLBAT = 0x82 + MEWTWO = 0x83 + SNORLAX = 0x84 + MAGIKARP = 0x85 + MISSINGNO_86 = 0x86 + MISSINGNO_87 = 0x87 + MUK = 0x88 + MISSINGNO_89 = 0x89 + KINGLER = 0x8A + CLOYSTER = 0x8B + MISSINGNO_8C = 0x8C + ELECTRODE = 0x8D + CLEFABLE = 0x8E + WEEZING = 0x8F + PERSIAN = 0x90 + MAROWAK = 0x91 + MISSINGNO_92 = 0x92 + HAUNTER = 0x93 + ABRA = 0x94 + ALAKAZAM = 0x95 + PIDGEOTTO = 0x96 + PIDGEOT = 0x97 + STARMIE = 0x98 + BULBASAUR = 0x99 + VENUSAUR = 0x9A + TENTACRUEL = 0x9B + MISSINGNO_9C = 0x9C + GOLDEEN = 0x9D + SEAKING = 0x9E + MISSINGNO_9F = 0x9F + MISSINGNO_A0 = 0xA0 + MISSINGNO_A1 = 0xA1 + MISSINGNO_A2 = 0xA2 + PONYTA = 0xA3 + RAPIDASH = 0xA4 + RATTATA = 0xA5 + RATICATE = 0xA6 + NIDORINO = 0xA7 + NIDORINA = 0xA8 + GEODUDE = 0xA9 + PORYGON = 0xAA + AERODACTYL = 0xAB + MISSINGNO_AC = 0xAC + MAGNEMITE = 0xAD + MISSINGNO_AE = 0xAE + MISSINGNO_AF = 0xAF + CHARMANDER = 0xB0 + SQUIRTLE = 0xB1 + CHARMELEON = 0xB2 + WARTORTLE = 0xB3 + CHARIZARD = 0xB4 + MISSINGNO_B5 = 0xB5 + FOSSIL_KABUTOPS = 0xB6 + FOSSIL_AERODACTYL = 0xB7 + MON_GHOST = 0xB8 + ODDISH = 0xB9 + GLOOM = 0xBA + VILEPLUME = 0xBB + BELLSPROUT = 0xBC + WEEPINBELL = 0xBD + VICTREEBEL = 0xBE ITEM_MASTER_BALL = 0x01 ITEM_ULTRA_BALL = 0x02 @@ -1092,7 +1093,7 @@ class Moves(Enum): STATUS_FROZEN = 32 STATUS_PARALYZED = 64 -MONSTER_NAMES = ( +NAMES = ( "Bulbasaur", "Ivysaur", "Venusaur", From c44d9259fa1cfeb114e29433262747192be6c605 Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Sat, 4 Nov 2023 18:06:24 -0400 Subject: [PATCH 12/74] Convert Items into Enum --- .../game_wrapper_pokemon_gen1/constants.py | 305 +++++++++--------- 1 file changed, 153 insertions(+), 152 deletions(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py b/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py index be91704bb..55d75e163 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py @@ -361,158 +361,159 @@ class Pokemon(Enum): WEEPINBELL = 0xBD VICTREEBEL = 0xBE -ITEM_MASTER_BALL = 0x01 -ITEM_ULTRA_BALL = 0x02 -ITEM_GREAT_BALL = 0x03 -ITEM_POKE_BALL = 0x04 -ITEM_TOWN_MAP = 0x05 -ITEM_BICYCLE = 0x06 -ITEM_SURFBOARD = 0x07 -ITEM_SAFARI_BALL = 0x08 -ITEM_POKEDEX = 0x09 -ITEM_MOON_STONE = 0x0A -ITEM_ANTIDOTE = 0x0B -ITEM_BURN_HEAL = 0x0C -ITEM_ICE_HEAL = 0x0D -ITEM_AWAKENING = 0x0E -ITEM_PARLYZ_HEAL = 0x0F -ITEM_FULL_RESTORE = 0x10 -ITEM_MAX_POTION = 0x11 -ITEM_HYPER_POTION = 0x12 -ITEM_SUPER_POTION = 0x13 -ITEM_POTION = 0x14 -ITEM_BOULDERBADGE = 0x15 -ITEM_CASCADEBADGE = 0x16 -ITEM_THUNDERBADGE = 0x17 -ITEM_RAINBOWBADGE = 0x18 -ITEM_SOULBADGE = 0x19 -ITEM_MARSHBADGE = 0x1A -ITEM_VOLCANOBADGE = 0x1B -ITEM_EARTHBADGE = 0x1C -ITEM_ESCAPE_ROPE = 0x1D -ITEM_REPEL = 0x1E -ITEM_OLD_AMBER = 0x1F -ITEM_FIRE_STONE = 0x20 -ITEM_THUNDER_STONE = 0x21 -ITEM_WATER_STONE = 0x22 -ITEM_HP_UP = 0x23 -ITEM_PROTEIN = 0x24 -ITEM_IRON = 0x25 -ITEM_CARBOS = 0x26 -ITEM_CALCIUM = 0x27 -ITEM_RARE_CANDY = 0x28 -ITEM_DOME_FOSSIL = 0x29 -ITEM_HELIX_FOSSIL = 0x2A -ITEM_SECRET_KEY = 0x2B -ITEM_UNUSED_ITEM = 0x2C -ITEM_BIKE_VOUCHER = 0x2D -ITEM_X_ACCURACY = 0x2E -ITEM_LEAF_STONE = 0x2F -ITEM_CARD_KEY = 0x30 -ITEM_NUGGET = 0x31 -ITEM_PP_UP_2 = 0x32 -ITEM_POKE_DOLL = 0x33 -ITEM_FULL_HEAL = 0x34 -ITEM_REVIVE = 0x35 -ITEM_MAX_REVIVE = 0x36 -ITEM_GUARD_SPEC = 0x37 -ITEM_SUPER_REPEL = 0x38 -ITEM_MAX_REPEL = 0x39 -ITEM_DIRE_HIT = 0x3A -ITEM_COIN = 0x3B -ITEM_FRESH_WATER = 0x3C -ITEM_SODA_POP = 0x3D -ITEM_LEMONADE = 0x3E -ITEM_S_S_TICKET = 0x3F -ITEM_GOLD_TEETH = 0x40 -ITEM_X_ATTACK = 0x41 -ITEM_X_DEFEND = 0x42 -ITEM_X_SPEED = 0x43 -ITEM_X_SPECIAL = 0x44 -ITEM_COIN_CASE = 0x45 -ITEM_OAKS_PARCEL = 0x46 -ITEM_ITEMFINDER = 0x47 -ITEM_SILPH_SCOPE = 0x48 -ITEM_POKE_FLUTE = 0x49 -ITEM_LIFT_KEY = 0x4A -ITEM_EXP_ALL = 0x4B -ITEM_OLD_ROD = 0x4C -ITEM_GOOD_ROD = 0x4D -ITEM_SUPER_ROD = 0x4E -ITEM_PP_UP = 0x4F -ITEM_ETHER = 0x50 -ITEM_MAX_ETHER = 0x51 -ITEM_ELIXER = 0x52 -ITEM_MAX_ELIXER = 0x53 -ITEM_FLOOR_B2F = 0x54 -ITEM_FLOOR_B1F = 0x55 -ITEM_FLOOR_1F = 0x56 -ITEM_FLOOR_2F = 0x57 -ITEM_FLOOR_3F = 0x58 -ITEM_FLOOR_4F = 0x59 -ITEM_FLOOR_5F = 0x5A -ITEM_FLOOR_6F = 0x5B -ITEM_FLOOR_7F = 0x5C -ITEM_FLOOR_8F = 0x5D -ITEM_FLOOR_9F = 0x5E -ITEM_FLOOR_10F = 0x5F -ITEM_FLOOR_11F = 0x60 -ITEM_FLOOR_B4F = 0x61 -ITEM_HM_01 = 0xC4 -ITEM_HM_02 = 0xC5 -ITEM_HM_03 = 0xC6 -ITEM_HM_04 = 0xC7 -ITEM_HM_05 = 0xC8 -ITEM_TM_01 = 0xC9 -ITEM_TM_02 = 0xCA -ITEM_TM_03 = 0xCB -ITEM_TM_04 = 0xCC -ITEM_TM_05 = 0xCD -ITEM_TM_06 = 0xCE -ITEM_TM_07 = 0xCF -ITEM_TM_08 = 0xD0 -ITEM_TM_09 = 0xD1 -ITEM_TM_10 = 0xD2 -ITEM_TM_11 = 0xD3 -ITEM_TM_12 = 0xD4 -ITEM_TM_13 = 0xD5 -ITEM_TM_14 = 0xD6 -ITEM_TM_15 = 0xD7 -ITEM_TM_16 = 0xD8 -ITEM_TM_17 = 0xD9 -ITEM_TM_18 = 0xDA -ITEM_TM_19 = 0xDB -ITEM_TM_20 = 0xDC -ITEM_TM_21 = 0xDD -ITEM_TM_22 = 0xDE -ITEM_TM_23 = 0xDF -ITEM_TM_24 = 0xE0 -ITEM_TM_25 = 0xE1 -ITEM_TM_26 = 0xE2 -ITEM_TM_27 = 0xE3 -ITEM_TM_28 = 0xE4 -ITEM_TM_29 = 0xE5 -ITEM_TM_30 = 0xE6 -ITEM_TM_31 = 0xE7 -ITEM_TM_32 = 0xE8 -ITEM_TM_33 = 0xE9 -ITEM_TM_34 = 0xEA -ITEM_TM_35 = 0xEB -ITEM_TM_36 = 0xEC -ITEM_TM_37 = 0xED -ITEM_TM_38 = 0xEE -ITEM_TM_39 = 0xEF -ITEM_TM_40 = 0xF0 -ITEM_TM_41 = 0xF1 -ITEM_TM_42 = 0xF2 -ITEM_TM_43 = 0xF3 -ITEM_TM_44 = 0xF4 -ITEM_TM_45 = 0xF5 -ITEM_TM_46 = 0xF6 -ITEM_TM_47 = 0xF7 -ITEM_TM_48 = 0xF8 -ITEM_TM_49 = 0xF9 -ITEM_TM_50 = 0xFA +class Items(Enum): + MASTER_BALL = 0x01 + ULTRA_BALL = 0x02 + GREAT_BALL = 0x03 + POKE_BALL = 0x04 + TOWN_MAP = 0x05 + BICYCLE = 0x06 + SURFBOARD = 0x07 + SAFARI_BALL = 0x08 + POKEDEX = 0x09 + MOON_STONE = 0x0A + ANTIDOTE = 0x0B + BURN_HEAL = 0x0C + ICE_HEAL = 0x0D + AWAKENING = 0x0E + PARLYZ_HEAL = 0x0F + FULL_RESTORE = 0x10 + MAX_POTION = 0x11 + HYPER_POTION = 0x12 + SUPER_POTION = 0x13 + POTION = 0x14 + BOULDERBADGE = 0x15 + CASCADEBADGE = 0x16 + THUNDERBADGE = 0x17 + RAINBOWBADGE = 0x18 + SOULBADGE = 0x19 + MARSHBADGE = 0x1A + VOLCANOBADGE = 0x1B + EARTHBADGE = 0x1C + ESCAPE_ROPE = 0x1D + REPEL = 0x1E + OLD_AMBER = 0x1F + FIRE_STONE = 0x20 + THUNDER_STONE = 0x21 + WATER_STONE = 0x22 + HP_UP = 0x23 + PROTEIN = 0x24 + IRON = 0x25 + CARBOS = 0x26 + CALCIUM = 0x27 + RARE_CANDY = 0x28 + DOME_FOSSIL = 0x29 + HELIX_FOSSIL = 0x2A + SECRET_KEY = 0x2B + UNUSED_ITEM = 0x2C + BIKE_VOUCHER = 0x2D + X_ACCURACY = 0x2E + LEAF_STONE = 0x2F + CARD_KEY = 0x30 + NUGGET = 0x31 + PP_UP_2 = 0x32 + POKE_DOLL = 0x33 + FULL_HEAL = 0x34 + REVIVE = 0x35 + MAX_REVIVE = 0x36 + GUARD_SPEC = 0x37 + SUPER_REPEL = 0x38 + MAX_REPEL = 0x39 + DIRE_HIT = 0x3A + COIN = 0x3B + FRESH_WATER = 0x3C + SODA_POP = 0x3D + LEMONADE = 0x3E + S_S_TICKET = 0x3F + GOLD_TEETH = 0x40 + X_ATTACK = 0x41 + X_DEFEND = 0x42 + X_SPEED = 0x43 + X_SPECIAL = 0x44 + COIN_CASE = 0x45 + OAKS_PARCEL = 0x46 + ITEMFINDER = 0x47 + SILPH_SCOPE = 0x48 + POKE_FLUTE = 0x49 + LIFT_KEY = 0x4A + EXP_ALL = 0x4B + OLD_ROD = 0x4C + GOOD_ROD = 0x4D + SUPER_ROD = 0x4E + PP_UP = 0x4F + ETHER = 0x50 + MAX_ETHER = 0x51 + ELIXER = 0x52 + MAX_ELIXER = 0x53 + FLOOR_B2F = 0x54 + FLOOR_B1F = 0x55 + FLOOR_1F = 0x56 + FLOOR_2F = 0x57 + FLOOR_3F = 0x58 + FLOOR_4F = 0x59 + FLOOR_5F = 0x5A + FLOOR_6F = 0x5B + FLOOR_7F = 0x5C + FLOOR_8F = 0x5D + FLOOR_9F = 0x5E + FLOOR_10F = 0x5F + FLOOR_11F = 0x60 + FLOOR_B4F = 0x61 + HM_01 = 0xC4 + HM_02 = 0xC5 + HM_03 = 0xC6 + HM_04 = 0xC7 + HM_05 = 0xC8 + TM_01 = 0xC9 + TM_02 = 0xCA + TM_03 = 0xCB + TM_04 = 0xCC + TM_05 = 0xCD + TM_06 = 0xCE + TM_07 = 0xCF + TM_08 = 0xD0 + TM_09 = 0xD1 + TM_10 = 0xD2 + TM_11 = 0xD3 + TM_12 = 0xD4 + TM_13 = 0xD5 + TM_14 = 0xD6 + TM_15 = 0xD7 + TM_16 = 0xD8 + TM_17 = 0xD9 + TM_18 = 0xDA + TM_19 = 0xDB + TM_20 = 0xDC + TM_21 = 0xDD + TM_22 = 0xDE + TM_23 = 0xDF + TM_24 = 0xE0 + TM_25 = 0xE1 + TM_26 = 0xE2 + TM_27 = 0xE3 + TM_28 = 0xE4 + TM_29 = 0xE5 + TM_30 = 0xE6 + TM_31 = 0xE7 + TM_32 = 0xE8 + TM_33 = 0xE9 + TM_34 = 0xEA + TM_35 = 0xEB + TM_36 = 0xEC + TM_37 = 0xED + TM_38 = 0xEE + TM_39 = 0xEF + TM_40 = 0xF0 + TM_41 = 0xF1 + TM_42 = 0xF2 + TM_43 = 0xF3 + TM_44 = 0xF4 + TM_45 = 0xF5 + TM_46 = 0xF6 + TM_47 = 0xF7 + TM_48 = 0xF8 + TM_49 = 0xF9 + TM_50 = 0xFA SPRITE_RED = 0x01 SPRITE_BLUE = 0x02 From d3d53987c73c173a52fa884969c05b68f9a4268d Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Sat, 4 Nov 2023 18:07:14 -0400 Subject: [PATCH 13/74] Convert Sprites into Enum --- .../game_wrapper_pokemon_gen1/constants.py | 145 +++++++++--------- 1 file changed, 73 insertions(+), 72 deletions(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py b/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py index 55d75e163..9dbfcf6bb 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py @@ -515,78 +515,79 @@ class Items(Enum): TM_49 = 0xF9 TM_50 = 0xFA -SPRITE_RED = 0x01 -SPRITE_BLUE = 0x02 -SPRITE_OAK = 0x03 -SPRITE_BUG_CATCHER = 0x04 -SPRITE_SLOWBRO = 0x05 -SPRITE_LASS = 0x06 -SPRITE_BLACK_HAIR_BOY_1 = 0x07 -SPRITE_LITTLE_GIRL = 0x08 -SPRITE_BIRD = 0x09 -SPRITE_FAT_BALD_GUY = 0x0a -SPRITE_GAMBLER = 0x0b -SPRITE_BLACK_HAIR_BOY_2 = 0x0c -SPRITE_GIRL = 0x0d -SPRITE_HIKER = 0x0e -SPRITE_FOULARD_WOMAN = 0x0f -SPRITE_GENTLEMAN = 0x10 -SPRITE_DAISY = 0x11 -SPRITE_BIKER = 0x12 -SPRITE_SAILOR = 0x13 -SPRITE_COOK = 0x14 -SPRITE_BIKE_SHOP_GUY = 0x15 -SPRITE_MR_FUJI = 0x16 -SPRITE_GIOVANNI = 0x17 -SPRITE_ROCKET = 0x18 -SPRITE_MEDIUM = 0x19 -SPRITE_WAITER = 0x1a -SPRITE_ERIKA = 0x1b -SPRITE_MOM_GEISHA = 0x1c -SPRITE_BRUNETTE_GIRL = 0x1d -SPRITE_LANCE = 0x1e -SPRITE_OAK_SCIENTIST_AIDE = 0x1f -SPRITE_OAK_AIDE = 0x20 -SPRITE_ROCKER = 0x21 -SPRITE_SWIMMER = 0x22 -SPRITE_WHITE_PLAYER = 0x23 -SPRITE_GYM_HELPER = 0x24 -SPRITE_OLD_PERSON = 0x25 -SPRITE_MART_GUY = 0x26 -SPRITE_FISHER = 0x27 -SPRITE_OLD_MEDIUM_WOMAN = 0x28 -SPRITE_NURSE = 0x29 -SPRITE_CABLE_CLUB_WOMAN = 0x2a -SPRITE_MR_MASTERBALL = 0x2b -SPRITE_LAPRAS_GIVER = 0x2c -SPRITE_WARDEN = 0x2d -SPRITE_SS_CAPTAIN = 0x2e -SPRITE_FISHER2 = 0x2f -SPRITE_BLACKBELT = 0x30 -SPRITE_GUARD = 0x31 -SPRITE_COP_GUARD = 0x32 -SPRITE_MOM = 0x33 -SPRITE_BALDING_GUY = 0x34 -SPRITE_YOUNG_BOY = 0x35 -SPRITE_GAMEBOY_KID = 0x36 -SPRITE_GAMEBOY_KID_COPY = 0x37 -SPRITE_CLEFAIRY = 0x38 -SPRITE_AGATHA = 0x39 -SPRITE_BRUNO = 0x3a -SPRITE_LORELEI = 0x3b -SPRITE_SEEL = 0x3c -SPRITE_BALL = 0x3d -SPRITE_OMANYTE = 0x3e -SPRITE_BOULDER = 0x3f -SPRITE_PAPER_SHEET = 0x40 -SPRITE_BOOK_MAP_DEX = 0x41 -SPRITE_CLIPBOARD = 0x42 -SPRITE_SNORLAX = 0x43 -SPRITE_OLD_AMBER_COPY = 0x44 -SPRITE_OLD_AMBER = 0x45 -SPRITE_LYING_OLD_MAN_UNUSED_1 = 0x46 -SPRITE_LYING_OLD_MAN_UNUSED_2 = 0x47 -SPRITE_LYING_OLD_MAN = 0x48 +class Sprites(Enum): + RED = 0x01 + BLUE = 0x02 + OAK = 0x03 + BUG_CATCHER = 0x04 + SLOWBRO = 0x05 + LASS = 0x06 + BLACK_HAIR_BOY_1 = 0x07 + LITTLE_GIRL = 0x08 + BIRD = 0x09 + FAT_BALD_GUY = 0x0a + GAMBLER = 0x0b + BLACK_HAIR_BOY_2 = 0x0c + GIRL = 0x0d + HIKER = 0x0e + FOULARD_WOMAN = 0x0f + GENTLEMAN = 0x10 + DAISY = 0x11 + BIKER = 0x12 + SAILOR = 0x13 + COOK = 0x14 + BIKE_SHOP_GUY = 0x15 + MR_FUJI = 0x16 + GIOVANNI = 0x17 + ROCKET = 0x18 + MEDIUM = 0x19 + WAITER = 0x1a + ERIKA = 0x1b + MOM_GEISHA = 0x1c + BRUNETTE_GIRL = 0x1d + LANCE = 0x1e + OAK_SCIENTIST_AIDE = 0x1f + OAK_AIDE = 0x20 + ROCKER = 0x21 + SWIMMER = 0x22 + WHITE_PLAYER = 0x23 + GYM_HELPER = 0x24 + OLD_PERSON = 0x25 + MART_GUY = 0x26 + FISHER = 0x27 + OLD_MEDIUM_WOMAN = 0x28 + NURSE = 0x29 + CABLE_CLUB_WOMAN = 0x2a + MR_MASTERBALL = 0x2b + LAPRAS_GIVER = 0x2c + WARDEN = 0x2d + SS_CAPTAIN = 0x2e + FISHER2 = 0x2f + BLACKBELT = 0x30 + GUARD = 0x31 + COP_GUARD = 0x32 + MOM = 0x33 + BALDING_GUY = 0x34 + YOUNG_BOY = 0x35 + GAMEBOY_KID = 0x36 + GAMEBOY_KID_COPY = 0x37 + CLEFAIRY = 0x38 + AGATHA = 0x39 + BRUNO = 0x3a + LORELEI = 0x3b + SEEL = 0x3c + BALL = 0x3d + OMANYTE = 0x3e + BOULDER = 0x3f + PAPER_SHEET = 0x40 + BOOK_MAP_DEX = 0x41 + CLIPBOARD = 0x42 + SNORLAX = 0x43 + OLD_AMBER_COPY = 0x44 + OLD_AMBER = 0x45 + LYING_OLD_MAN_UNUSED_1 = 0x46 + LYING_OLD_MAN_UNUSED_2 = 0x47 + LYING_OLD_MAN = 0x48 MAP_PALLET_TOWN = 0x00 MAP_VIRIDIAN_CITY = 0x01 From 935ac55b3e973abb78706df149ec305ea87319ea Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Sat, 4 Nov 2023 18:09:40 -0400 Subject: [PATCH 14/74] Convert Maps into Enum --- .../game_wrapper_pokemon_gen1/constants.py | 497 +++++++++--------- 1 file changed, 249 insertions(+), 248 deletions(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py b/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py index 9dbfcf6bb..72c4502e6 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py @@ -589,254 +589,255 @@ class Sprites(Enum): LYING_OLD_MAN_UNUSED_2 = 0x47 LYING_OLD_MAN = 0x48 -MAP_PALLET_TOWN = 0x00 -MAP_VIRIDIAN_CITY = 0x01 -MAP_PEWTER_CITY = 0x02 -MAP_CERULEAN_CITY = 0x03 -MAP_LAVENDER_TOWN = 0x04 -MAP_VERMILION_CITY = 0x05 -MAP_CELADON_CITY = 0x06 -MAP_FUCHSIA_CITY = 0x07 -MAP_CINNABAR_ISLAND = 0x08 -MAP_INDIGO_PLATEAU = 0x09 -MAP_SAFFRON_CITY = 0x0A -MAP_UNUSED_MAP_0B = 0x0B -MAP_ROUTE_1 = 0x0C -MAP_ROUTE_2 = 0x0D -MAP_ROUTE_3 = 0x0E -MAP_ROUTE_4 = 0x0F -MAP_ROUTE_5 = 0x10 -MAP_ROUTE_6 = 0x11 -MAP_ROUTE_7 = 0x12 -MAP_ROUTE_8 = 0x13 -MAP_ROUTE_9 = 0x14 -MAP_ROUTE_10 = 0x15 -MAP_ROUTE_11 = 0x16 -MAP_ROUTE_12 = 0x17 -MAP_ROUTE_13 = 0x18 -MAP_ROUTE_14 = 0x19 -MAP_ROUTE_15 = 0x1A -MAP_ROUTE_16 = 0x1B -MAP_ROUTE_17 = 0x1C -MAP_ROUTE_18 = 0x1D -MAP_ROUTE_19 = 0x1E -MAP_ROUTE_20 = 0x1F -MAP_ROUTE_21 = 0x20 -MAP_ROUTE_22 = 0x21 -MAP_ROUTE_23 = 0x22 -MAP_ROUTE_24 = 0x23 -MAP_ROUTE_25 = 0x24 -MAP_REDS_HOUSE_1F = 0x25 -MAP_REDS_HOUSE_2F = 0x26 -MAP_BLUES_HOUSE = 0x27 -MAP_OAKS_LAB = 0x28 -MAP_VIRIDIAN_POKECENTER = 0x29 -MAP_VIRIDIAN_MART = 0x2A -MAP_VIRIDIAN_SCHOOL_HOUSE = 0x2B -MAP_VIRIDIAN_NICKNAME_HOUSE = 0x2C -MAP_VIRIDIAN_GYM = 0x2D -MAP_DIGLETTS_CAVE_ROUTE_2 = 0x2E -MAP_VIRIDIAN_FOREST_NORTH_GATE = 0x2F -MAP_ROUTE_2_TRADE_HOUSE = 0x30 -MAP_ROUTE_2_GATE = 0x31 -MAP_VIRIDIAN_FOREST_SOUTH_GATE = 0x32 -MAP_VIRIDIAN_FOREST = 0x33 -MAP_MUSEUM_1F = 0x34 -MAP_MUSEUM_2F = 0x35 -MAP_PEWTER_GYM = 0x36 -MAP_PEWTER_NIDORAN_HOUSE = 0x37 -MAP_PEWTER_MART = 0x38 -MAP_PEWTER_SPEECH_HOUSE = 0x39 -MAP_PEWTER_POKECENTER = 0x3A -MAP_MT_MOON_1F = 0x3B -MAP_MT_MOON_B1F = 0x3C -MAP_MT_MOON_B2F = 0x3D -MAP_CERULEAN_TRASHED_HOUSE = 0x3E -MAP_CERULEAN_TRADE_HOUSE = 0x3F -MAP_CERULEAN_POKECENTER = 0x40 -MAP_CERULEAN_GYM = 0x41 -MAP_BIKE_SHOP = 0x42 -MAP_CERULEAN_MART = 0x43 -MAP_MT_MOON_POKECENTER = 0x44 -MAP_CERULEAN_TRASHED_HOUSE_COPY = 0x45 -MAP_ROUTE_5_GATE = 0x46 -MAP_UNDERGROUND_PATH_ROUTE_5 = 0x47 -MAP_DAYCARE = 0x48 -MAP_ROUTE_6_GATE = 0x49 -MAP_UNDERGROUND_PATH_ROUTE_6 = 0x4A -MAP_UNDERGROUND_PATH_ROUTE_6_COPY = 0x4B -MAP_ROUTE_7_GATE = 0x4C -MAP_UNDERGROUND_PATH_ROUTE_7 = 0x4D -MAP_UNDERGROUND_PATH_ROUTE_7_COPY = 0x4E -MAP_ROUTE_8_GATE = 0x4F -MAP_UNDERGROUND_PATH_ROUTE_8 = 0x50 -MAP_ROCK_TUNNEL_POKECENTER = 0x51 -MAP_ROCK_TUNNEL_1F = 0x52 -MAP_POWER_PLANT = 0x53 -MAP_ROUTE_11_GATE_1F = 0x54 -MAP_DIGLETTS_CAVE_ROUTE_11 = 0x55 -MAP_ROUTE_11_GATE_2F = 0x56 -MAP_ROUTE_12_GATE_1F = 0x57 -MAP_BILLS_HOUSE = 0x58 -MAP_VERMILION_POKECENTER = 0x59 -MAP_POKEMON_FAN_CLUB = 0x5A -MAP_VERMILION_MART = 0x5B -MAP_VERMILION_GYM = 0x5C -MAP_VERMILION_PIDGEY_HOUSE = 0x5D -MAP_VERMILION_DOCK = 0x5E -MAP_SS_ANNE_1F = 0x5F -MAP_SS_ANNE_2F = 0x60 -MAP_SS_ANNE_3F = 0x61 -MAP_SS_ANNE_B1F = 0x62 -MAP_SS_ANNE_BOW = 0x63 -MAP_SS_ANNE_KITCHEN = 0x64 -MAP_SS_ANNE_CAPTAINS_ROOM = 0x65 -MAP_SS_ANNE_1F_ROOMS = 0x66 -MAP_SS_ANNE_2F_ROOMS = 0x67 -MAP_SS_ANNE_B1F_ROOMS = 0x68 -MAP_UNUSED_MAP_69 = 0x69 -MAP_UNUSED_MAP_6A = 0x6A -MAP_UNUSED_MAP_6B = 0x6B -MAP_VICTORY_ROAD_1F = 0x6C -MAP_UNUSED_MAP_6D = 0x6D -MAP_UNUSED_MAP_6E = 0x6E -MAP_UNUSED_MAP_6F = 0x6F -MAP_UNUSED_MAP_70 = 0x70 -MAP_LANCES_ROOM = 0x71 -MAP_UNUSED_MAP_72 = 0x72 -MAP_UNUSED_MAP_73 = 0x73 -MAP_UNUSED_MAP_74 = 0x74 -MAP_UNUSED_MAP_75 = 0x75 -MAP_HALL_OF_FAME = 0x76 -MAP_UNDERGROUND_PATH_NORTH_SOUTH = 0x77 -MAP_CHAMPIONS_ROOM = 0x78 -MAP_UNDERGROUND_PATH_WEST_EAST = 0x79 -MAP_CELADON_MART_1F = 0x7A -MAP_CELADON_MART_2F = 0x7B -MAP_CELADON_MART_3F = 0x7C -MAP_CELADON_MART_4F = 0x7D -MAP_CELADON_MART_ROOF = 0x7E -MAP_CELADON_MART_ELEVATOR = 0x7F -MAP_CELADON_MANSION_1F = 0x80 -MAP_CELADON_MANSION_2F = 0x81 -MAP_CELADON_MANSION_3F = 0x82 -MAP_CELADON_MANSION_ROOF = 0x83 -MAP_CELADON_MANSION_ROOF_HOUSE = 0x84 -MAP_CELADON_POKECENTER = 0x85 -MAP_CELADON_GYM = 0x86 -MAP_GAME_CORNER = 0x87 -MAP_CELADON_MART_5F = 0x88 -MAP_GAME_CORNER_PRIZE_ROOM = 0x89 -MAP_CELADON_DINER = 0x8A -MAP_CELADON_CHIEF_HOUSE = 0x8B -MAP_CELADON_HOTEL = 0x8C -MAP_LAVENDER_POKECENTER = 0x8D -MAP_POKEMON_TOWER_1F = 0x8E -MAP_POKEMON_TOWER_2F = 0x8F -MAP_POKEMON_TOWER_3F = 0x90 -MAP_POKEMON_TOWER_4F = 0x91 -MAP_POKEMON_TOWER_5F = 0x92 -MAP_POKEMON_TOWER_6F = 0x93 -MAP_POKEMON_TOWER_7F = 0x94 -MAP_MR_FUJIS_HOUSE = 0x95 -MAP_LAVENDER_MART = 0x96 -MAP_LAVENDER_CUBONE_HOUSE = 0x97 -MAP_FUCHSIA_MART = 0x98 -MAP_FUCHSIA_BILLS_GRANDPAS_HOUSE = 0x99 -MAP_FUCHSIA_POKECENTER = 0x9A -MAP_WARDENS_HOUSE = 0x9B -MAP_SAFARI_ZONE_GATE = 0x9C -MAP_FUCHSIA_GYM = 0x9D -MAP_FUCHSIA_MEETING_ROOM = 0x9E -MAP_SEAFOAM_ISLANDS_B1F = 0x9F -MAP_SEAFOAM_ISLANDS_B2F = 0xA0 -MAP_SEAFOAM_ISLANDS_B3F = 0xA1 -MAP_SEAFOAM_ISLANDS_B4F = 0xA2 -MAP_VERMILION_OLD_ROD_HOUSE = 0xA3 -MAP_FUCHSIA_GOOD_ROD_HOUSE = 0xA4 -MAP_POKEMON_MANSION_1F = 0xA5 -MAP_CINNABAR_GYM = 0xA6 -MAP_CINNABAR_LAB = 0xA7 -MAP_CINNABAR_LAB_TRADE_ROOM = 0xA8 -MAP_CINNABAR_LAB_METRONOME_ROOM = 0xA9 -MAP_CINNABAR_LAB_FOSSIL_ROOM = 0xAA -MAP_CINNABAR_POKECENTER = 0xAB -MAP_CINNABAR_MART = 0xAC -MAP_CINNABAR_MART_COPY = 0xAD -MAP_INDIGO_PLATEAU_LOBBY = 0xAE -MAP_COPYCATS_HOUSE_1F = 0xAF -MAP_COPYCATS_HOUSE_2F = 0xB0 -MAP_FIGHTING_DOJO = 0xB1 -MAP_SAFFRON_GYM = 0xB2 -MAP_SAFFRON_PIDGEY_HOUSE = 0xB3 -MAP_SAFFRON_MART = 0xB4 -MAP_SILPH_CO_1F = 0xB5 -MAP_SAFFRON_POKECENTER = 0xB6 -MAP_MR_PSYCHICS_HOUSE = 0xB7 -MAP_ROUTE_15_GATE_1F = 0xB8 -MAP_ROUTE_15_GATE_2F = 0xB9 -MAP_ROUTE_16_GATE_1F = 0xBA -MAP_ROUTE_16_GATE_2F = 0xBB -MAP_ROUTE_16_FLY_HOUSE = 0xBC -MAP_ROUTE_12_SUPER_ROD_HOUSE = 0xBD -MAP_ROUTE_18_GATE_1F = 0xBE -MAP_ROUTE_18_GATE_2F = 0xBF -MAP_SEAFOAM_ISLANDS_1F = 0xC0 -MAP_ROUTE_22_GATE = 0xC1 -MAP_VICTORY_ROAD_2F = 0xC2 -MAP_ROUTE_12_GATE_2F = 0xC3 -MAP_VERMILION_TRADE_HOUSE = 0xC4 -MAP_DIGLETTS_CAVE = 0xC5 -MAP_VICTORY_ROAD_3F = 0xC6 -MAP_ROCKET_HIDEOUT_B1F = 0xC7 -MAP_ROCKET_HIDEOUT_B2F = 0xC8 -MAP_ROCKET_HIDEOUT_B3F = 0xC9 -MAP_ROCKET_HIDEOUT_B4F = 0xCA -MAP_ROCKET_HIDEOUT_ELEVATOR = 0xCB -MAP_UNUSED_MAP_CC = 0xCC -MAP_UNUSED_MAP_CD = 0xCD -MAP_UNUSED_MAP_CE = 0xCE -MAP_SILPH_CO_2F = 0xCF -MAP_SILPH_CO_3F = 0xD0 -MAP_SILPH_CO_4F = 0xD1 -MAP_SILPH_CO_5F = 0xD2 -MAP_SILPH_CO_6F = 0xD3 -MAP_SILPH_CO_7F = 0xD4 -MAP_SILPH_CO_8F = 0xD5 -MAP_POKEMON_MANSION_2F = 0xD6 -MAP_POKEMON_MANSION_3F = 0xD7 -MAP_POKEMON_MANSION_B1F = 0xD8 -MAP_SAFARI_ZONE_EAST = 0xD9 -MAP_SAFARI_ZONE_NORTH = 0xDA -MAP_SAFARI_ZONE_WEST = 0xDB -MAP_SAFARI_ZONE_CENTER = 0xDC -MAP_SAFARI_ZONE_CENTER_REST_HOUSE = 0xDD -MAP_SAFARI_ZONE_SECRET_HOUSE = 0xDE -MAP_SAFARI_ZONE_WEST_REST_HOUSE = 0xDF -MAP_SAFARI_ZONE_EAST_REST_HOUSE = 0xE0 -MAP_SAFARI_ZONE_NORTH_REST_HOUSE = 0xE1 -MAP_CERULEAN_CAVE_2F = 0xE2 -MAP_CERULEAN_CAVE_B1F = 0xE3 -MAP_CERULEAN_CAVE_1F = 0xE4 -MAP_NAME_RATERS_HOUSE = 0xE5 -MAP_CERULEAN_BADGE_HOUSE = 0xE6 -MAP_UNUSED_MAP_E7 = 0xE7 -MAP_ROCK_TUNNEL_B1F = 0xE8 -MAP_SILPH_CO_9F = 0xE9 -MAP_SILPH_CO_10F = 0xEA -MAP_SILPH_CO_11F = 0xEB -MAP_SILPH_CO_ELEVATOR = 0xEC -MAP_UNUSED_MAP_ED = 0xED -MAP_UNUSED_MAP_EE = 0xEE -MAP_TRADE_CENTER = 0xEF -MAP_COLOSSEUM = 0xF0 -MAP_UNUSED_MAP_F1 = 0xF1 -MAP_UNUSED_MAP_F2 = 0xF2 -MAP_UNUSED_MAP_F3 = 0xF3 -MAP_UNUSED_MAP_F4 = 0xF4 -MAP_LORELEIS_ROOM = 0xF5 -MAP_BRUNOS_ROOM = 0xF6 -MAP_AGATHAS_ROOM = 0xF7 +class Maps(Enum): + PALLET_TOWN = 0x00 + VIRIDIAN_CITY = 0x01 + PEWTER_CITY = 0x02 + CERULEAN_CITY = 0x03 + LAVENDER_TOWN = 0x04 + VERMILION_CITY = 0x05 + CELADON_CITY = 0x06 + FUCHSIA_CITY = 0x07 + CINNABAR_ISLAND = 0x08 + INDIGO_PLATEAU = 0x09 + SAFFRON_CITY = 0x0A + UNUSED_MAP_0B = 0x0B + ROUTE_1 = 0x0C + ROUTE_2 = 0x0D + ROUTE_3 = 0x0E + ROUTE_4 = 0x0F + ROUTE_5 = 0x10 + ROUTE_6 = 0x11 + ROUTE_7 = 0x12 + ROUTE_8 = 0x13 + ROUTE_9 = 0x14 + ROUTE_10 = 0x15 + ROUTE_11 = 0x16 + ROUTE_12 = 0x17 + ROUTE_13 = 0x18 + ROUTE_14 = 0x19 + ROUTE_15 = 0x1A + ROUTE_16 = 0x1B + ROUTE_17 = 0x1C + ROUTE_18 = 0x1D + ROUTE_19 = 0x1E + ROUTE_20 = 0x1F + ROUTE_21 = 0x20 + ROUTE_22 = 0x21 + ROUTE_23 = 0x22 + ROUTE_24 = 0x23 + ROUTE_25 = 0x24 + REDS_HOUSE_1F = 0x25 + REDS_HOUSE_2F = 0x26 + BLUES_HOUSE = 0x27 + OAKS_LAB = 0x28 + VIRIDIAN_POKECENTER = 0x29 + VIRIDIAN_MART = 0x2A + VIRIDIAN_SCHOOL_HOUSE = 0x2B + VIRIDIAN_NICKNAME_HOUSE = 0x2C + VIRIDIAN_GYM = 0x2D + DIGLETTS_CAVE_ROUTE_2 = 0x2E + VIRIDIAN_FOREST_NORTH_GATE = 0x2F + ROUTE_2_TRADE_HOUSE = 0x30 + ROUTE_2_GATE = 0x31 + VIRIDIAN_FOREST_SOUTH_GATE = 0x32 + VIRIDIAN_FOREST = 0x33 + MUSEUM_1F = 0x34 + MUSEUM_2F = 0x35 + PEWTER_GYM = 0x36 + PEWTER_NIDORAN_HOUSE = 0x37 + PEWTER_MART = 0x38 + PEWTER_SPEECH_HOUSE = 0x39 + PEWTER_POKECENTER = 0x3A + MT_MOON_1F = 0x3B + MT_MOON_B1F = 0x3C + MT_MOON_B2F = 0x3D + CERULEAN_TRASHED_HOUSE = 0x3E + CERULEAN_TRADE_HOUSE = 0x3F + CERULEAN_POKECENTER = 0x40 + CERULEAN_GYM = 0x41 + BIKE_SHOP = 0x42 + CERULEAN_MART = 0x43 + MT_MOON_POKECENTER = 0x44 + CERULEAN_TRASHED_HOUSE_COPY = 0x45 + ROUTE_5_GATE = 0x46 + UNDERGROUND_PATH_ROUTE_5 = 0x47 + DAYCARE = 0x48 + ROUTE_6_GATE = 0x49 + UNDERGROUND_PATH_ROUTE_6 = 0x4A + UNDERGROUND_PATH_ROUTE_6_COPY = 0x4B + ROUTE_7_GATE = 0x4C + UNDERGROUND_PATH_ROUTE_7 = 0x4D + UNDERGROUND_PATH_ROUTE_7_COPY = 0x4E + ROUTE_8_GATE = 0x4F + UNDERGROUND_PATH_ROUTE_8 = 0x50 + ROCK_TUNNEL_POKECENTER = 0x51 + ROCK_TUNNEL_1F = 0x52 + POWER_PLANT = 0x53 + ROUTE_11_GATE_1F = 0x54 + DIGLETTS_CAVE_ROUTE_11 = 0x55 + ROUTE_11_GATE_2F = 0x56 + ROUTE_12_GATE_1F = 0x57 + BILLS_HOUSE = 0x58 + VERMILION_POKECENTER = 0x59 + POKEMON_FAN_CLUB = 0x5A + VERMILION_MART = 0x5B + VERMILION_GYM = 0x5C + VERMILION_PIDGEY_HOUSE = 0x5D + VERMILION_DOCK = 0x5E + SS_ANNE_1F = 0x5F + SS_ANNE_2F = 0x60 + SS_ANNE_3F = 0x61 + SS_ANNE_B1F = 0x62 + SS_ANNE_BOW = 0x63 + SS_ANNE_KITCHEN = 0x64 + SS_ANNE_CAPTAINS_ROOM = 0x65 + SS_ANNE_1F_ROOMS = 0x66 + SS_ANNE_2F_ROOMS = 0x67 + SS_ANNE_B1F_ROOMS = 0x68 + UNUSED_MAP_69 = 0x69 + UNUSED_MAP_6A = 0x6A + UNUSED_MAP_6B = 0x6B + VICTORY_ROAD_1F = 0x6C + UNUSED_MAP_6D = 0x6D + UNUSED_MAP_6E = 0x6E + UNUSED_MAP_6F = 0x6F + UNUSED_MAP_70 = 0x70 + LANCES_ROOM = 0x71 + UNUSED_MAP_72 = 0x72 + UNUSED_MAP_73 = 0x73 + UNUSED_MAP_74 = 0x74 + UNUSED_MAP_75 = 0x75 + HALL_OF_FAME = 0x76 + UNDERGROUND_PATH_NORTH_SOUTH = 0x77 + CHAMPIONS_ROOM = 0x78 + UNDERGROUND_PATH_WEST_EAST = 0x79 + CELADON_MART_1F = 0x7A + CELADON_MART_2F = 0x7B + CELADON_MART_3F = 0x7C + CELADON_MART_4F = 0x7D + CELADON_MART_ROOF = 0x7E + CELADON_MART_ELEVATOR = 0x7F + CELADON_MANSION_1F = 0x80 + CELADON_MANSION_2F = 0x81 + CELADON_MANSION_3F = 0x82 + CELADON_MANSION_ROOF = 0x83 + CELADON_MANSION_ROOF_HOUSE = 0x84 + CELADON_POKECENTER = 0x85 + CELADON_GYM = 0x86 + GAME_CORNER = 0x87 + CELADON_MART_5F = 0x88 + GAME_CORNER_PRIZE_ROOM = 0x89 + CELADON_DINER = 0x8A + CELADON_CHIEF_HOUSE = 0x8B + CELADON_HOTEL = 0x8C + LAVENDER_POKECENTER = 0x8D + POKEMON_TOWER_1F = 0x8E + POKEMON_TOWER_2F = 0x8F + POKEMON_TOWER_3F = 0x90 + POKEMON_TOWER_4F = 0x91 + POKEMON_TOWER_5F = 0x92 + POKEMON_TOWER_6F = 0x93 + POKEMON_TOWER_7F = 0x94 + MR_FUJIS_HOUSE = 0x95 + LAVENDER_MART = 0x96 + LAVENDER_CUBONE_HOUSE = 0x97 + FUCHSIA_MART = 0x98 + FUCHSIA_BILLS_GRANDPAS_HOUSE = 0x99 + FUCHSIA_POKECENTER = 0x9A + WARDENS_HOUSE = 0x9B + SAFARI_ZONE_GATE = 0x9C + FUCHSIA_GYM = 0x9D + FUCHSIA_MEETING_ROOM = 0x9E + SEAFOAM_ISLANDS_B1F = 0x9F + SEAFOAM_ISLANDS_B2F = 0xA0 + SEAFOAM_ISLANDS_B3F = 0xA1 + SEAFOAM_ISLANDS_B4F = 0xA2 + VERMILION_OLD_ROD_HOUSE = 0xA3 + FUCHSIA_GOOD_ROD_HOUSE = 0xA4 + POKEMON_MANSION_1F = 0xA5 + CINNABAR_GYM = 0xA6 + CINNABAR_LAB = 0xA7 + CINNABAR_LAB_TRADE_ROOM = 0xA8 + CINNABAR_LAB_METRONOME_ROOM = 0xA9 + CINNABAR_LAB_FOSSIL_ROOM = 0xAA + CINNABAR_POKECENTER = 0xAB + CINNABAR_MART = 0xAC + CINNABAR_MART_COPY = 0xAD + INDIGO_PLATEAU_LOBBY = 0xAE + COPYCATS_HOUSE_1F = 0xAF + COPYCATS_HOUSE_2F = 0xB0 + FIGHTING_DOJO = 0xB1 + SAFFRON_GYM = 0xB2 + SAFFRON_PIDGEY_HOUSE = 0xB3 + SAFFRON_MART = 0xB4 + SILPH_CO_1F = 0xB5 + SAFFRON_POKECENTER = 0xB6 + MR_PSYCHICS_HOUSE = 0xB7 + ROUTE_15_GATE_1F = 0xB8 + ROUTE_15_GATE_2F = 0xB9 + ROUTE_16_GATE_1F = 0xBA + ROUTE_16_GATE_2F = 0xBB + ROUTE_16_FLY_HOUSE = 0xBC + ROUTE_12_SUPER_ROD_HOUSE = 0xBD + ROUTE_18_GATE_1F = 0xBE + ROUTE_18_GATE_2F = 0xBF + SEAFOAM_ISLANDS_1F = 0xC0 + ROUTE_22_GATE = 0xC1 + VICTORY_ROAD_2F = 0xC2 + ROUTE_12_GATE_2F = 0xC3 + VERMILION_TRADE_HOUSE = 0xC4 + DIGLETTS_CAVE = 0xC5 + VICTORY_ROAD_3F = 0xC6 + ROCKET_HIDEOUT_B1F = 0xC7 + ROCKET_HIDEOUT_B2F = 0xC8 + ROCKET_HIDEOUT_B3F = 0xC9 + ROCKET_HIDEOUT_B4F = 0xCA + ROCKET_HIDEOUT_ELEVATOR = 0xCB + UNUSED_MAP_CC = 0xCC + UNUSED_MAP_CD = 0xCD + UNUSED_MAP_CE = 0xCE + SILPH_CO_2F = 0xCF + SILPH_CO_3F = 0xD0 + SILPH_CO_4F = 0xD1 + SILPH_CO_5F = 0xD2 + SILPH_CO_6F = 0xD3 + SILPH_CO_7F = 0xD4 + SILPH_CO_8F = 0xD5 + POKEMON_MANSION_2F = 0xD6 + POKEMON_MANSION_3F = 0xD7 + POKEMON_MANSION_B1F = 0xD8 + SAFARI_ZONE_EAST = 0xD9 + SAFARI_ZONE_NORTH = 0xDA + SAFARI_ZONE_WEST = 0xDB + SAFARI_ZONE_CENTER = 0xDC + SAFARI_ZONE_CENTER_REST_HOUSE = 0xDD + SAFARI_ZONE_SECRET_HOUSE = 0xDE + SAFARI_ZONE_WEST_REST_HOUSE = 0xDF + SAFARI_ZONE_EAST_REST_HOUSE = 0xE0 + SAFARI_ZONE_NORTH_REST_HOUSE = 0xE1 + CERULEAN_CAVE_2F = 0xE2 + CERULEAN_CAVE_B1F = 0xE3 + CERULEAN_CAVE_1F = 0xE4 + NAME_RATERS_HOUSE = 0xE5 + CERULEAN_BADGE_HOUSE = 0xE6 + UNUSED_MAP_E7 = 0xE7 + ROCK_TUNNEL_B1F = 0xE8 + SILPH_CO_9F = 0xE9 + SILPH_CO_10F = 0xEA + SILPH_CO_11F = 0xEB + SILPH_CO_ELEVATOR = 0xEC + UNUSED_MAP_ED = 0xED + UNUSED_MAP_EE = 0xEE + TRADE_CENTER = 0xEF + COLOSSEUM = 0xF0 + UNUSED_MAP_F1 = 0xF1 + UNUSED_MAP_F2 = 0xF2 + UNUSED_MAP_F3 = 0xF3 + UNUSED_MAP_F4 = 0xF4 + LORELEIS_ROOM = 0xF5 + BRUNOS_ROOM = 0xF6 + AGATHAS_ROOM = 0xF7 MAP_NAMES = [ 'PALLET TOWN', From 24efb7a16f6b3000bed2d67aee68b852aab2fe39 Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Sat, 4 Nov 2023 18:10:36 -0400 Subject: [PATCH 15/74] Convert Statuses into Enum --- pyboy/plugins/game_wrapper_pokemon_gen1/constants.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py b/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py index 72c4502e6..7906675a5 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py @@ -1090,11 +1090,12 @@ class Maps(Enum): 'AGATHA\'S ROOM', ] -STATUS_ASLEEP = 4 -STATUS_POISONED = 8 -STATUS_BURNED = 16 -STATUS_FROZEN = 32 -STATUS_PARALYZED = 64 +class Status(Enum): + ASLEEP = 4 + POISONED = 8 + BURNED = 16 + FROZEN = 32 + PARALYZED = 64 NAMES = ( "Bulbasaur", From be72c8fd86d45f16c7e07df1a84b52f69f01e58d Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Sat, 4 Nov 2023 18:13:17 -0400 Subject: [PATCH 16/74] Raname Status Enum to Statuses (which was the original intent) --- pyboy/plugins/game_wrapper_pokemon_gen1/constants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py b/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py index 7906675a5..eba0ff0ee 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py @@ -1090,7 +1090,7 @@ class Maps(Enum): 'AGATHA\'S ROOM', ] -class Status(Enum): +class Statuses(Enum): ASLEEP = 4 POISONED = 8 BURNED = 16 From 19983906dc9f4eecf52271524530b45e78cd1ef1 Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Sat, 4 Nov 2023 20:07:17 -0400 Subject: [PATCH 17/74] Create Pokemon class to wrap memory loading of all values of a pokemon in the party --- .../game_wrapper_pokemon_gen1.py | 123 +--------------- .../gen_1_memory_manager.py | 136 +++++++++++++++--- 2 files changed, 116 insertions(+), 143 deletions(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py index 8276f1ac9..e83e3b6ce 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py @@ -188,127 +188,8 @@ def get_text(self, address, cap = 16): def set_palette_to_darkness(self): self.pyboy.set_memory_value(0xD35D, 6) - def set_player_monster(self, index, monster): - """ - Sets player monster at a given index. - - Args: - index (int): Which monster to change (0-5). - monster (int): Which type of monster to set. - """ - self.pyboy.set_memory_value(0xD16B + index, monster) - self.pyboy.set_memory_value(0xD164 + (index * PKMN_SIZE), monster) - - def get_player_monster(self, index): - """ - Returns player monster at a given index. - - Args: - index (int): Which monster to change (0-5). - """ - return self.memory_manager.get_pokemon_1_info() - - def set_player_monster_nickname(self, index, text): - """ - Sets player monster's nickname at a given index. - - Args: - index (int): Which monster to change (0-5). - text (string): Nickname to set (will be trimmed at 10 characters). - """ - self.set_text(text[:10], 0xD2B5 + (index * PKMN_SIZE)) - - def get_player_monster_nickname(self, index): - """ - Returns player monster's nickname at a given index. - - Args: - index (int): Which monster (0-5). - """ - return self.get_text(0xD2B5 + (index * PKMN_SIZE)) - - def set_player_monster_move(self, index, move_index, move): - """ - Sets player monster's move at a given index. - - Args: - index (int): Which monster to change (0-5). - move_index (int): Which move to change (0-3). - move (int): Which type of move to set. - """ - self.pyboy.set_memory_value(0xD01C + (index * PKMN_SIZE) + move_index, move) - - def get_player_monster_move(self, index, move_index): - """ - Returns player monster's move at a given index. - - Args: - index (int): Which monster (0-5). - move_index (int): Which move to change (0-3). - """ - return self.pyboy.get_memory_value(0xD01C + (index * PKMN_SIZE) + move_index) - - def get_player_monster_current_hp(self, index): - """ - Returns player monster's current HP at a given index. - - Args: - index (int): Which monster (0-5). - """ - return self.get_int_at_address(0xD16C + (index * PKMN_SIZE)) - - def get_active_player_monster_current_hp(self): - return self.get_int_at_address(0xD015) - - def set_player_monster_current_hp(self, index, hp): - """ - Sets the current HP of a given player monster. - - Args: - index (int): Which monster to change (0-5). - hp (int): Health points. - """ - self.set_int_at_address(0xD16C + (index * PKMN_SIZE), hp) - - def set_active_player_monster_current_hp(self, hp): - self.set_int_at_address(0xD015, hp) - - def get_player_monster_max_hp(self, index): - """ - Returns player monster's max HP at a given index. - - Args: - index (int): Which monster (0-5). - """ - return self.get_int_at_address(0xD18D + (index * PKMN_SIZE)) - - def get_active_player_monster_max_hp(self): - return self.get_int_at_address(0xD023) - - def set_player_monster_max_hp(self, index, hp): - """ - Sets the max HP of a given player monster. - - Args: - index (int): Which monster to change (0-5). - hp (int): Health points. - """ - self.set_int_at_address(0xD18D + (index * PKMN_SIZE), hp) - - def set_active_player_monster_max_hp(self, hp): - return self.set_int_at_address(0xD023, hp) - - def set_player_monster_status(self, index, status): - """ - Sets the ailment status of a given player monster. - - Args: - index (int): Which monster to change (0-5). - status (int): Status to be set. - """ - assert status >= 0 and status < 0xFF - assert index < 6 - self.pyboy.set_memory_value(0xD16F + (index * PKMN_SIZE), status) + def get_pokemon(self, party_index): + return self.memory_manager.load_pokemon_from_party(party_index) def set_player_monster_asleep(self, index): self.set_player_monster_status(index, constants.STATUS_ASLEEP) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/gen_1_memory_manager.py b/pyboy/plugins/game_wrapper_pokemon_gen1/gen_1_memory_manager.py index 1e9981b00..330d82262 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/gen_1_memory_manager.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/gen_1_memory_manager.py @@ -7,35 +7,127 @@ HRAM = (0xFF80, 0xFFFE) # Pokemon locations in memory -POKEMON_1_BASE = 0xD16B -POKEMON_2_BASE = 0xD197 -POKEMON_3_BASE = 0xD1C3 -POKEMON_4_BASE = 0xD1EF -POKEMON_5_BASE = 0xD21B -POKEMON_6_BASE = 0xD247 +class PokemonBaseAddrs(Enum): + POKEMON_1 = 0xD16B + POKEMON_2 = 0xD197 + POKEMON_3 = 0xD1C3 + POKEMON_4 = 0xD1EF + POKEMON_5 = 0xD21B + POKEMON_6 = 0xD247 # Offsets for Pokemon data access # Structure is (offset, num bytes) -POKEMON_OFFSET = (0x0, 1) -POKEMON_CURRENT_HP_OFFSET = (0x1, 2) -POKEMON_STATUS_OFFSET = (0x3, 1) -POKEMON_TYPE_1_OFFSET = (0x4, 1) -POKEMON_TYPE_2_OFFSET = (0x5, 1) -POKEMON_CATCH_RATE_OFFSET = (0x6, 1) -POKEMON_MOVE_1_OFFSET = (0x7, 1) -POKEMON_MOVE_2_OFFSET = (0x8, 1) -POKEMON_MOVE_3_OFFSET = (0x9, 1) -POKEMON_MOVE_4_OFFSET = (0xA, 1) -POKEMON_TRAINER_ID_OFFSET = (0xB, 2) -POKEMON_EXPERIENCE_OFFSET = (0xD, 3) - -POKEMON_LEVEL_OFFSET = (0x21, 1) +class PokemonOffsets(Enum): + ID = (0x0, 1) + CURRENT_HP = (0x1, 2) + STATUS = (0x3, 1) + TYPE_1 = (0x4, 1) + TYPE_2 = (0x5, 1) + CATCH_RATE = (0x6, 1) + MOVE_1 = (0x7, 1) + MOVE_2 = (0x8, 1) + MOVE_3 = (0x9, 1) + MOVE_4 = (0xA, 1) + TRAINER_ID = (0xB, 2) + EXPERIENCE = (0xD, 3) + HP_EV = (0x11, 2) + ATTACK_EV = (0x13, 2) + DEFENSE_EV = (0x15, 2) + SPEED_EV = (0x17, 2) + SPECIAL_EV = (0x19, 2) + ATTACK_DEFENSE_IV = (0x1B, 1) + SPEED_SPECIAL_IV = (0x1C, 1) + PP_MOVE_1 = (0x1D, 1) + PP_MOVE_2 = (0x1E, 1) + PP_MOVE_3 = (0x1F, 1) + PP_MOVE_4 = (0x20, 1) + LEVEL = (0x21, 1) + MAX_HP = (0x22, 2) + ATTACK = (0x24, 2) + DEFENSE = (0x26, 2) + SPEED = (0x28, 2) + SPECIAL = (0x2A, 2) +class Pokemon: + + def __init__(self, + pokemon_id, + current_hp, + status, + type_1, + type_2, + catch_rate, + move_1, + move_2, + move_3, + move_4, + trainer_id, + experience, + hp_ev, + attack_ev, + defense_ev, + speed_ev, + special_ev, + attack_defense_iv, + speed_special_iv, + pp_move_1, + pp_move_2, + pp_move_3, + pp_move_4, + level, + max_hp, + attack, + defense, + speed, + special): + self.pokemon_id = pokemon_id + self.current_hp = current_hp + self.status = status + self.type_1 = type_1 + self.type_2 = type_2 + self.catch_rate = catch_rate + self.move_1 = move_1 + self.move_2 = move_2 + self.move_3 = move_3 + self.move_4 = move_4 + self.trainer_id = trainer_id + self.experience = experience + self.hp_ev = hp_ev + self.attack_ev = attack_ev + self.defense_ev = defense_ev + self.speed_ev = speed_ev + self.special_ev = special_ev + self.attack_defense_iv = attack_defense_iv + self.speed_special_iv = speed_special_iv + self.pp_move_1 = pp_move_1 + self.pp_move_2 = pp_move_2 + self.pp_move_3 = pp_move_3 + self.pp_move_4 = pp_move_4 + self.level = level + self.max_hp = max_hp + self.attack = attack + self.defense = defense + self.speed = speed + self.special = special + class Gen1MemoryManager: def __init__(self, pyboy, byte_order='big'): self.pyboy = pyboy self.byte_order = byte_order - def get_pokemon_1_info(self): - return self.pyboy.get_memory_value(POKEMON_1_BASE + LEVEL[0]) + def _load_pokemon_from_address(self, pokemon_base_address): + + pokemon_values = [] + + for offset_enum in PokemonOffsets: + offset, num_bytes = offset_enum.value[0], offset_enum.value[1] + memory_value = self.pyboy.get_memory_value(pokemon_base_address+offset, num_bytes) + pokemon_values.append(memory_value) + + return Pokemon(*pokemon_values) + + def load_pokemon_from_party(self, party_location): + # party_location goes from 1 to 6 + pokemon_base_address = list(PokemonBaseAddrs)[party_location-1].value + return self._load_pokemon_from_address(pokemon_base_address) \ No newline at end of file From 4b08aefb97f512cf018c1969e9c8f0f38cb30456 Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Sun, 5 Nov 2023 20:14:59 -0500 Subject: [PATCH 18/74] Start recreating PokemonPOkedexIndex enum --- .../game_wrapper_pokemon_gen1/constants.py | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py b/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py index eba0ff0ee..f4c247ed3 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py @@ -1251,6 +1251,44 @@ class Statuses(Enum): "Mew", ) +class PokemonPokedexIndex(Enum): + BULBASAUR = 1 + IVYSAUR = 2 + VENUSAUR = 3 + CHARMANDER = 4 + CHARMELEON = 5 + CHARIZARD = 6 + SQUIRTLE = 7 + WARTORTLE = 8 + BLASTOISE = 9 + CATERPIE = 10 + METAPOD = 11 + BUTTERFREE = 12 + WEEDLE = 13 + KAKUNA = 14 + BEEDRILL = 15 + PIDGEY = 16 + PIDGEOTTO = 17 + PIDGEOT = 18 + RATTATA = 19 + RATICATE = 20 + SPEAROW = 21 + FEAROW = 22 + EKANS = 23 + ARBOK = 24 + PIKACHU = 25 + RAICHU = 26 + SANDSHREW = 27 + SANDSLASH = 28 + NIDORAN_F = 29 + NIDORINA = 30 + NIDOQUEEN = 31 + NIDORAN_M = 32 + NIDORINO = 33 + NIDOKING = 34 + CLEFAIRY = 35 + + POKEDEX_TO_INDEX_MAP = ( (112, 0x01), (115, 0x02), From 1439fc0496e636c8490544297d8d0bce8257f017 Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Sun, 5 Nov 2023 20:15:45 -0500 Subject: [PATCH 19/74] Define pretty print function for Pokemon type --- .../game_wrapper_pokemon_gen1/gen_1_memory_manager.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/gen_1_memory_manager.py b/pyboy/plugins/game_wrapper_pokemon_gen1/gen_1_memory_manager.py index 330d82262..b2a6aab1c 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/gen_1_memory_manager.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/gen_1_memory_manager.py @@ -109,6 +109,11 @@ def __init__(self, self.defense = defense self.speed = speed self.special = special + + def pretty_stringify(self): + s = ''' + + ''' class Gen1MemoryManager: From 2e4a2dc25a747ec7d829f8f19eacc84836a3d701 Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Sun, 5 Nov 2023 20:56:12 -0500 Subject: [PATCH 20/74] Convert pokedex entry lookup into a dictionary with a Pokemon Enum key --- .../game_wrapper_pokemon_gen1/constants.py | 189 ++++++++++++++---- 1 file changed, 153 insertions(+), 36 deletions(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py b/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py index f4c247ed3..c33c923e0 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py @@ -1251,42 +1251,159 @@ class Statuses(Enum): "Mew", ) -class PokemonPokedexIndex(Enum): - BULBASAUR = 1 - IVYSAUR = 2 - VENUSAUR = 3 - CHARMANDER = 4 - CHARMELEON = 5 - CHARIZARD = 6 - SQUIRTLE = 7 - WARTORTLE = 8 - BLASTOISE = 9 - CATERPIE = 10 - METAPOD = 11 - BUTTERFREE = 12 - WEEDLE = 13 - KAKUNA = 14 - BEEDRILL = 15 - PIDGEY = 16 - PIDGEOTTO = 17 - PIDGEOT = 18 - RATTATA = 19 - RATICATE = 20 - SPEAROW = 21 - FEAROW = 22 - EKANS = 23 - ARBOK = 24 - PIKACHU = 25 - RAICHU = 26 - SANDSHREW = 27 - SANDSLASH = 28 - NIDORAN_F = 29 - NIDORINA = 30 - NIDOQUEEN = 31 - NIDORAN_M = 32 - NIDORINO = 33 - NIDOKING = 34 - CLEFAIRY = 35 +POKEMON_POKEDEX_INDEX = { + Pokemon.BULBASAUR: 1, + Pokemon.IVYSAUR: 2, + Pokemon.VENUSAUR: 3, + Pokemon.CHARMANDER: 4, + Pokemon.CHARMELEON: 5, + Pokemon.CHARIZARD: 6, + Pokemon.SQUIRTLE: 7, + Pokemon.WARTORTLE: 8, + Pokemon.BLASTOISE: 9, + Pokemon.CATERPIE: 10, + Pokemon.METAPOD: 11, + Pokemon.BUTTERFREE: 12, + Pokemon.WEEDLE: 13, + Pokemon.KAKUNA: 14, + Pokemon.BEEDRILL: 15, + Pokemon.PIDGEY: 16, + Pokemon.PIDGEOTTO: 17, + Pokemon.PIDGEOT: 18, + Pokemon.RATTATA: 19, + Pokemon.RATICATE: 20, + Pokemon.SPEAROW: 21, + Pokemon.FEAROW: 22, + Pokemon.EKANS: 23, + Pokemon.ARBOK: 24, + Pokemon.PIKACHU: 25, + Pokemon.RAICHU: 26, + Pokemon.SANDSHREW: 27, + Pokemon.SANDSLASH: 28, + Pokemon.NIDORAN_F: 29, + Pokemon.NIDORINA: 30, + Pokemon.NIDOQUEEN: 31, + Pokemon.NIDORAN_M: 32, + Pokemon.NIDORINO: 33, + Pokemon.NIDOKING: 34, + Pokemon.CLEFAIRY: 35, + Pokemon.CLEFABLE: 36, + Pokemon.VULPIX: 37, + Pokemon.NINETALES: 38, + Pokemon.JIGGLYPUFF: 39, + Pokemon.WIGGLYTUFF: 40, + Pokemon.ZUBAT: 41, + Pokemon.GOLBAT: 42, + Pokemon.ODDISH: 43, + Pokemon.GLOOM: 44, + Pokemon.VILEPLUME: 45, + Pokemon.PARAS: 46, + Pokemon.PARASECT: 47, + Pokemon.VENONAT: 48, + Pokemon.VENOMOTH: 49, + Pokemon.DIGLETT: 50, + Pokemon.DUGTRIO: 51, + Pokemon.MEOWTH: 52, + Pokemon.PERSIAN: 53, + Pokemon.PSYDUCK: 54, + Pokemon.GOLDUCK: 55, + Pokemon.MANKEY: 56, + Pokemon.PRIMEAPE: 57, + Pokemon.GROWLITHE: 58, + Pokemon.ARCANINE: 59, + Pokemon.POLIWAG: 60, + Pokemon.POLIWHIRL: 61, + Pokemon.POLIWRATH: 62, + Pokemon.ABRA: 63, + Pokemon.KADABRA: 64, + Pokemon.ALAKAZAM: 65, + Pokemon.MACHOP: 66, + Pokemon.MACHOKE: 67, + Pokemon.MACHAMP: 68, + Pokemon.BELLSPROUT: 69, + Pokemon.WEEPINBELL: 70, + Pokemon.VICTREEBEL: 71, + Pokemon.TENTACOOL: 72, + Pokemon.TENTACRUEL: 73, + Pokemon.GEODUDE: 74, + Pokemon.GRAVELER: 75, + Pokemon.GOLEM: 76, + Pokemon.PONYTA: 77, + Pokemon.RAPIDASH: 78, + Pokemon.SLOWPOKE: 79, + Pokemon.SLOWBRO: 80, + Pokemon.MAGNEMITE: 81, + Pokemon.MAGNETON: 82, + Pokemon.FARFETCHD: 83, + Pokemon.DODUO: 84, + Pokemon.DODRIO: 85, + Pokemon.SEEL: 86, + Pokemon.DEWGONG: 87, + Pokemon.GRIMER: 88, + Pokemon.MUK: 89, + Pokemon.SHELLDER: 90, + Pokemon.CLOYSTER: 91, + Pokemon.GASTLY: 92, + Pokemon.HAUNTER: 93, + Pokemon.GENGAR: 94, + Pokemon.ONIX: 95, + Pokemon.DROWZEE: 96, + Pokemon.HYPNO: 97, + Pokemon.KRABBY: 98, + Pokemon.KINGLER: 99, + Pokemon.VOLTORB: 100, + Pokemon.ELECTRODE: 101, + Pokemon.EXEGGCUTE: 102, + Pokemon.EXEGGUTOR: 103, + Pokemon.CUBONE: 104, + Pokemon.MAROWAK: 105, + Pokemon.HITMONLEE: 106, + Pokemon.HITMONCHAN: 107, + Pokemon.LICKITUNG: 108, + Pokemon.KOFFING: 109, + Pokemon.WEEZING: 110, + Pokemon.RHYHORN: 111, + Pokemon.RHYDON: 112, + Pokemon.CHANSEY: 113, + Pokemon.TANGELA: 114, + Pokemon.KANGASKHAN: 115, + Pokemon.HORSEA: 116, + Pokemon.SEADRA: 117, + Pokemon.GOLDEEN: 118, + Pokemon.SEAKING: 119, + Pokemon.STARYU: 120, + Pokemon.STARMIE: 121, + Pokemon.MR_MIME: 122, + Pokemon.SCYTHER: 123, + Pokemon.JYNX: 124, + Pokemon.ELECTABUZZ: 125, + Pokemon.MAGMAR: 126, + Pokemon.PINSIR: 127, + Pokemon.TAUROS: 128, + Pokemon.MAGIKARP: 129, + Pokemon.GYARADOS: 130, + Pokemon.LAPRAS: 131, + Pokemon.DITTO: 132, + Pokemon.EEVEE: 133, + Pokemon.VAPOREON: 134, + Pokemon.JOLTEON: 135, + Pokemon.FLAREON: 136, + Pokemon.PORYGON: 137, + Pokemon.OMANYTE: 138, + Pokemon.OMASTAR: 139, + Pokemon.KABUTO: 140, + Pokemon.KABUTOPS: 141, + Pokemon.AERODACTYL: 142, + Pokemon.SNORLAX: 143, + Pokemon.ARTICUNO: 144, + Pokemon.ZAPDOS: 145, + Pokemon.MOLTRES: 146, + Pokemon.DRATINI: 147, + Pokemon.DRAGONAIR: 148, + Pokemon.DRAGONITE: 149, + Pokemon.MEWTWO: 150, + Pokemon.MEW: 151 +} POKEDEX_TO_INDEX_MAP = ( From 6abad359696b73534aabd59dd256b7e632db61c3 Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Mon, 6 Nov 2023 10:41:47 -0500 Subject: [PATCH 21/74] Break up constants.py into directory with smaller files so it's a little easier to parse the data --- .../constants/pokemon.py | 501 ++++++++++++++++++ 1 file changed, 501 insertions(+) create mode 100644 pyboy/plugins/game_wrapper_pokemon_gen1/constants/pokemon.py diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/constants/pokemon.py b/pyboy/plugins/game_wrapper_pokemon_gen1/constants/pokemon.py new file mode 100644 index 000000000..3655cc5c1 --- /dev/null +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/constants/pokemon.py @@ -0,0 +1,501 @@ +from enum import Enum + +class Pokemon(Enum): + RHYDON = 0x01 + KANGASKHAN = 0x02 + NIDORAN_M = 0x03 + CLEFAIRY = 0x04 + SPEAROW = 0x05 + VOLTORB = 0x06 + NIDOKING = 0x07 + SLOWBRO = 0x08 + IVYSAUR = 0x09 + EXEGGUTOR = 0x0A + LICKITUNG = 0x0B + EXEGGCUTE = 0x0C + GRIMER = 0x0D + GENGAR = 0x0E + NIDORAN_F = 0x0F + NIDOQUEEN = 0x10 + CUBONE = 0x11 + RHYHORN = 0x12 + LAPRAS = 0x13 + ARCANINE = 0x14 + MEW = 0x15 + GYARADOS = 0x16 + SHELLDER = 0x17 + TENTACOOL = 0x18 + GASTLY = 0x19 + SCYTHER = 0x1A + STARYU = 0x1B + BLASTOISE = 0x1C + PINSIR = 0x1D + TANGELA = 0x1E + MISSINGNO_1F = 0x1F + MISSINGNO_20 = 0x20 + GROWLITHE = 0x21 + ONIX = 0x22 + FEAROW = 0x23 + PIDGEY = 0x24 + SLOWPOKE = 0x25 + KADABRA = 0x26 + GRAVELER = 0x27 + CHANSEY = 0x28 + MACHOKE = 0x29 + MR_MIME = 0x2A + HITMONLEE = 0x2B + HITMONCHAN = 0x2C + ARBOK = 0x2D + PARASECT = 0x2E + PSYDUCK = 0x2F + DROWZEE = 0x30 + GOLEM = 0x31 + MISSINGNO_32 = 0x32 + MAGMAR = 0x33 + MISSINGNO_34 = 0x34 + ELECTABUZZ = 0x35 + MAGNETON = 0x36 + KOFFING = 0x37 + MISSINGNO_38 = 0x38 + MANKEY = 0x39 + SEEL = 0x3A + DIGLETT = 0x3B + TAUROS = 0x3C + MISSINGNO_3D = 0x3D + MISSINGNO_3E = 0x3E + MISSINGNO_3F = 0x3F + FARFETCHD = 0x40 + VENONAT = 0x41 + DRAGONITE = 0x42 + MISSINGNO_43 = 0x43 + MISSINGNO_44 = 0x44 + MISSINGNO_45 = 0x45 + DODUO = 0x46 + POLIWAG = 0x47 + JYNX = 0x48 + MOLTRES = 0x49 + ARTICUNO = 0x4A + ZAPDOS = 0x4B + DITTO = 0x4C + MEOWTH = 0x4D + KRABBY = 0x4E + MISSINGNO_4F = 0x4F + MISSINGNO_50 = 0x50 + MISSINGNO_51 = 0x51 + VULPIX = 0x52 + NINETALES = 0x53 + PIKACHU = 0x54 + RAICHU = 0x55 + MISSINGNO_56 = 0x56 + MISSINGNO_57 = 0x57 + DRATINI = 0x58 + DRAGONAIR = 0x59 + KABUTO = 0x5A + KABUTOPS = 0x5B + HORSEA = 0x5C + SEADRA = 0x5D + MISSINGNO_5E = 0x5E + MISSINGNO_5F = 0x5F + SANDSHREW = 0x60 + SANDSLASH = 0x61 + OMANYTE = 0x62 + OMASTAR = 0x63 + JIGGLYPUFF = 0x64 + WIGGLYTUFF = 0x65 + EEVEE = 0x66 + FLAREON = 0x67 + JOLTEON = 0x68 + VAPOREON = 0x69 + MACHOP = 0x6A + ZUBAT = 0x6B + EKANS = 0x6C + PARAS = 0x6D + POLIWHIRL = 0x6E + POLIWRATH = 0x6F + WEEDLE = 0x70 + KAKUNA = 0x71 + BEEDRILL = 0x72 + MISSINGNO_73 = 0x73 + DODRIO = 0x74 + PRIMEAPE = 0x75 + DUGTRIO = 0x76 + VENOMOTH = 0x77 + DEWGONG = 0x78 + MISSINGNO_79 = 0x79 + MISSINGNO_7A = 0x7A + CATERPIE = 0x7B + METAPOD = 0x7C + BUTTERFREE = 0x7D + MACHAMP = 0x7E + MISSINGNO_7F = 0x7F + GOLDUCK = 0x80 + HYPNO = 0x81 + GOLBAT = 0x82 + MEWTWO = 0x83 + SNORLAX = 0x84 + MAGIKARP = 0x85 + MISSINGNO_86 = 0x86 + MISSINGNO_87 = 0x87 + MUK = 0x88 + MISSINGNO_89 = 0x89 + KINGLER = 0x8A + CLOYSTER = 0x8B + MISSINGNO_8C = 0x8C + ELECTRODE = 0x8D + CLEFABLE = 0x8E + WEEZING = 0x8F + PERSIAN = 0x90 + MAROWAK = 0x91 + MISSINGNO_92 = 0x92 + HAUNTER = 0x93 + ABRA = 0x94 + ALAKAZAM = 0x95 + PIDGEOTTO = 0x96 + PIDGEOT = 0x97 + STARMIE = 0x98 + BULBASAUR = 0x99 + VENUSAUR = 0x9A + TENTACRUEL = 0x9B + MISSINGNO_9C = 0x9C + GOLDEEN = 0x9D + SEAKING = 0x9E + MISSINGNO_9F = 0x9F + MISSINGNO_A0 = 0xA0 + MISSINGNO_A1 = 0xA1 + MISSINGNO_A2 = 0xA2 + PONYTA = 0xA3 + RAPIDASH = 0xA4 + RATTATA = 0xA5 + RATICATE = 0xA6 + NIDORINO = 0xA7 + NIDORINA = 0xA8 + GEODUDE = 0xA9 + PORYGON = 0xAA + AERODACTYL = 0xAB + MISSINGNO_AC = 0xAC + MAGNEMITE = 0xAD + MISSINGNO_AE = 0xAE + MISSINGNO_AF = 0xAF + CHARMANDER = 0xB0 + SQUIRTLE = 0xB1 + CHARMELEON = 0xB2 + WARTORTLE = 0xB3 + CHARIZARD = 0xB4 + MISSINGNO_B5 = 0xB5 + FOSSIL_KABUTOPS = 0xB6 + FOSSIL_AERODACTYL = 0xB7 + MON_GHOST = 0xB8 + ODDISH = 0xB9 + GLOOM = 0xBA + VILEPLUME = 0xBB + BELLSPROUT = 0xBC + WEEPINBELL = 0xBD + VICTREEBEL = 0xBE + +POKEMON_POKEDEX_INDEX = { + Pokemon.BULBASAUR: 1, + Pokemon.IVYSAUR: 2, + Pokemon.VENUSAUR: 3, + Pokemon.CHARMANDER: 4, + Pokemon.CHARMELEON: 5, + Pokemon.CHARIZARD: 6, + Pokemon.SQUIRTLE: 7, + Pokemon.WARTORTLE: 8, + Pokemon.BLASTOISE: 9, + Pokemon.CATERPIE: 10, + Pokemon.METAPOD: 11, + Pokemon.BUTTERFREE: 12, + Pokemon.WEEDLE: 13, + Pokemon.KAKUNA: 14, + Pokemon.BEEDRILL: 15, + Pokemon.PIDGEY: 16, + Pokemon.PIDGEOTTO: 17, + Pokemon.PIDGEOT: 18, + Pokemon.RATTATA: 19, + Pokemon.RATICATE: 20, + Pokemon.SPEAROW: 21, + Pokemon.FEAROW: 22, + Pokemon.EKANS: 23, + Pokemon.ARBOK: 24, + Pokemon.PIKACHU: 25, + Pokemon.RAICHU: 26, + Pokemon.SANDSHREW: 27, + Pokemon.SANDSLASH: 28, + Pokemon.NIDORAN_F: 29, + Pokemon.NIDORINA: 30, + Pokemon.NIDOQUEEN: 31, + Pokemon.NIDORAN_M: 32, + Pokemon.NIDORINO: 33, + Pokemon.NIDOKING: 34, + Pokemon.CLEFAIRY: 35, + Pokemon.CLEFABLE: 36, + Pokemon.VULPIX: 37, + Pokemon.NINETALES: 38, + Pokemon.JIGGLYPUFF: 39, + Pokemon.WIGGLYTUFF: 40, + Pokemon.ZUBAT: 41, + Pokemon.GOLBAT: 42, + Pokemon.ODDISH: 43, + Pokemon.GLOOM: 44, + Pokemon.VILEPLUME: 45, + Pokemon.PARAS: 46, + Pokemon.PARASECT: 47, + Pokemon.VENONAT: 48, + Pokemon.VENOMOTH: 49, + Pokemon.DIGLETT: 50, + Pokemon.DUGTRIO: 51, + Pokemon.MEOWTH: 52, + Pokemon.PERSIAN: 53, + Pokemon.PSYDUCK: 54, + Pokemon.GOLDUCK: 55, + Pokemon.MANKEY: 56, + Pokemon.PRIMEAPE: 57, + Pokemon.GROWLITHE: 58, + Pokemon.ARCANINE: 59, + Pokemon.POLIWAG: 60, + Pokemon.POLIWHIRL: 61, + Pokemon.POLIWRATH: 62, + Pokemon.ABRA: 63, + Pokemon.KADABRA: 64, + Pokemon.ALAKAZAM: 65, + Pokemon.MACHOP: 66, + Pokemon.MACHOKE: 67, + Pokemon.MACHAMP: 68, + Pokemon.BELLSPROUT: 69, + Pokemon.WEEPINBELL: 70, + Pokemon.VICTREEBEL: 71, + Pokemon.TENTACOOL: 72, + Pokemon.TENTACRUEL: 73, + Pokemon.GEODUDE: 74, + Pokemon.GRAVELER: 75, + Pokemon.GOLEM: 76, + Pokemon.PONYTA: 77, + Pokemon.RAPIDASH: 78, + Pokemon.SLOWPOKE: 79, + Pokemon.SLOWBRO: 80, + Pokemon.MAGNEMITE: 81, + Pokemon.MAGNETON: 82, + Pokemon.FARFETCHD: 83, + Pokemon.DODUO: 84, + Pokemon.DODRIO: 85, + Pokemon.SEEL: 86, + Pokemon.DEWGONG: 87, + Pokemon.GRIMER: 88, + Pokemon.MUK: 89, + Pokemon.SHELLDER: 90, + Pokemon.CLOYSTER: 91, + Pokemon.GASTLY: 92, + Pokemon.HAUNTER: 93, + Pokemon.GENGAR: 94, + Pokemon.ONIX: 95, + Pokemon.DROWZEE: 96, + Pokemon.HYPNO: 97, + Pokemon.KRABBY: 98, + Pokemon.KINGLER: 99, + Pokemon.VOLTORB: 100, + Pokemon.ELECTRODE: 101, + Pokemon.EXEGGCUTE: 102, + Pokemon.EXEGGUTOR: 103, + Pokemon.CUBONE: 104, + Pokemon.MAROWAK: 105, + Pokemon.HITMONLEE: 106, + Pokemon.HITMONCHAN: 107, + Pokemon.LICKITUNG: 108, + Pokemon.KOFFING: 109, + Pokemon.WEEZING: 110, + Pokemon.RHYHORN: 111, + Pokemon.RHYDON: 112, + Pokemon.CHANSEY: 113, + Pokemon.TANGELA: 114, + Pokemon.KANGASKHAN: 115, + Pokemon.HORSEA: 116, + Pokemon.SEADRA: 117, + Pokemon.GOLDEEN: 118, + Pokemon.SEAKING: 119, + Pokemon.STARYU: 120, + Pokemon.STARMIE: 121, + Pokemon.MR_MIME: 122, + Pokemon.SCYTHER: 123, + Pokemon.JYNX: 124, + Pokemon.ELECTABUZZ: 125, + Pokemon.MAGMAR: 126, + Pokemon.PINSIR: 127, + Pokemon.TAUROS: 128, + Pokemon.MAGIKARP: 129, + Pokemon.GYARADOS: 130, + Pokemon.LAPRAS: 131, + Pokemon.DITTO: 132, + Pokemon.EEVEE: 133, + Pokemon.VAPOREON: 134, + Pokemon.JOLTEON: 135, + Pokemon.FLAREON: 136, + Pokemon.PORYGON: 137, + Pokemon.OMANYTE: 138, + Pokemon.OMASTAR: 139, + Pokemon.KABUTO: 140, + Pokemon.KABUTOPS: 141, + Pokemon.AERODACTYL: 142, + Pokemon.SNORLAX: 143, + Pokemon.ARTICUNO: 144, + Pokemon.ZAPDOS: 145, + Pokemon.MOLTRES: 146, + Pokemon.DRATINI: 147, + Pokemon.DRAGONAIR: 148, + Pokemon.DRAGONITE: 149, + Pokemon.MEWTWO: 150, + Pokemon.MEW: 151 +} + +POKEMON_NAMES = { + Pokemon.BULBASAUR: "Bulbasaur", + Pokemon.IVYSAUR: "Ivysaur", + Pokemon.VENUSAUR: "Venusaur", + Pokemon.CHARMANDER: "Charmander", + Pokemon.CHARMELEON: "Charmeleon", + Pokemon.CHARIZARD: "Charizard", + Pokemon.SQUIRTLE: "Squirtle", + Pokemon.WARTORTLE: "Wartortle", + Pokemon.BLASTOISE: "Blastoise", + Pokemon.CATERPIE: "Caterpie", + Pokemon.METAPOD: "Metapod", + Pokemon.BUTTERFREE: "Butterfree", + Pokemon.CATERPIE: "Weedle", + Pokemon.KAKUNA: "Kakuna", + Pokemon.BEEDRILL: "Beedrill", + Pokemon.PIDGEY: "Pidgey", + Pokemon.PIDGEOTTO: "Pidgeotto", + Pokemon.PIDGEOT: "Pidgeot", + Pokemon.RATTATA: "Rattata", + Pokemon.RATICATE: "Raticate", + Pokemon.SPEAROW: "Spearow", + Pokemon.FEAROW: "Fearow", + Pokemon.EKANS: "Ekans", + Pokemon.ARBOK: "Arbok", + Pokemon.PIKACHU: "Pikachu", + Pokemon.RAICHU: "Raichu", + Pokemon.SANDSHREW: "Sandshrew", + Pokemon.SANDSLASH: "Sandslash", + Pokemon.NIDORAN_F: "Nidoran♀", + Pokemon.NIDORINA: "Nidorina", + Pokemon.NIDOQUEEN: "Nidoqueen", + Pokemon.NIDORAN_M: "Nidoran♂", + Pokemon.NIDORINO: "Nidorino", + Pokemon.NIDOKING: "Nidoking", + Pokemon.CLEFAIRY: "Clefairy", + Pokemon.CLEFABLE: "Clefable", + Pokemon.VULPIX: "Vulpix", + Pokemon.NINETALES: "Ninetales", + Pokemon.JIGGLYPUFF: "Jigglypuff", + Pokemon.WIGGLYTUFF: "Wigglytuff", + Pokemon.ZUBAT: "Zubat", + Pokemon.GOLBAT: "Golbat", + Pokemon.ODDISH: "Oddish", + Pokemon.GLOOM: "Gloom", + Pokemon.VILEPLUME: "Vileplume", + Pokemon.PARAS: "Paras", + Pokemon.PARASECT: "Parasect", + Pokemon.VENONAT: "Venonat", + Pokemon.VENOMOTH: "Venomoth", + Pokemon.DIGLETT: "Diglett", + Pokemon.DUGTRIO: "Dugtrio", + Pokemon.MEOWTH: "Meowth", + Pokemon.PERSIAN: "Persian", + Pokemon.PSYDUCK: "Psyduck", + Pokemon.GOLDUCK: "Golduck", + Pokemon.MANKEY: "Mankey", + Pokemon.PRIMEAPE: "Primeape", + Pokemon.GROWLITHE: "Growlithe", + Pokemon.ARCANINE: "Arcanine", + Pokemon.POLIWAG: "Poliwag", + Pokemon.POLIWHIRL: "Poliwhirl", + Pokemon.POLIWRATH: "Poliwrath", + Pokemon.ABRA: "Abra", + Pokemon.KADABRA: "Kadabra", + Pokemon.ALAKAZAM: "Alakazam", + Pokemon.MACHOP: "Machop", + Pokemon.MACHOKE: "Machoke", + Pokemon.MACHAMP: "Machamp", + Pokemon.BELLSPROUT: "Bellsprout", + Pokemon.WEEPINBELL: "Weepinbell", + Pokemon.VICTREEBEL: "Victreebel", + Pokemon.TENTACOOL: "Tentacool", + Pokemon.TENTACRUEL: "Tentacruel", + Pokemon.GEODUDE: "Geodude", + Pokemon.GRAVELER: "Graveler", + Pokemon.GOLEM: "Golem", + Pokemon.PONYTA: "Ponyta", + Pokemon.RAPIDASH: "Rapidash", + Pokemon.SLOWPOKE: "Slowpoke", + Pokemon.SLOWBRO: "Slowbro", + Pokemon.MAGNEMITE: "Magnemite", + Pokemon.MAGNETON: "Magneton", + Pokemon.FARFETCHD: "Farfetch’d", + Pokemon.DODUO: "Doduo", + Pokemon.DODRIO: "Dodrio", + Pokemon.SEEL: "Seel", + Pokemon.DEWGONG: "Dewgong", + Pokemon.GRIMER: "Grimer", + Pokemon.MUK: "Muk", + Pokemon.SHELLDER: "Shellder", + Pokemon.CLOYSTER: "Cloyster", + Pokemon.GASTLY: "Gastly", + Pokemon.HAUNTER: "Haunter", + Pokemon.GENGAR: "Gengar", + Pokemon.ONIX: "Onix", + Pokemon.DROWZEE: "Drowzee", + Pokemon.HYPNO: "Hypno", + Pokemon.KRABBY: "Krabby", + Pokemon.KINGLER: "Kingler", + Pokemon.VOLTORB: "Voltorb", + Pokemon.ELECTRODE: "Electrode", + Pokemon.EXEGGCUTE: "Exeggcute", + Pokemon.EXEGGUTOR: "Exeggutor", + Pokemon.CUBONE: "Cubone", + Pokemon.MAROWAK: "Marowak", + Pokemon.HITMONLEE: "Hitmonlee", + Pokemon.HITMONCHAN: "Hitmonchan", + Pokemon.LICKITUNG: "Lickitung", + Pokemon.KOFFING: "Koffing", + Pokemon.WEEZING: "Weezing", + Pokemon.RHYHORN: "Rhyhorn", + Pokemon.RHYDON: "Rhydon", + Pokemon.CHANSEY: "Chansey", + Pokemon.TANGELA: "Tangela", + Pokemon.KANGASKHAN: "Kangaskhan", + Pokemon.HORSEA: "Horsea", + Pokemon.SEADRA: "Seadra", + Pokemon.GOLDEEN: "Goldeen", + Pokemon.SEAKING: "Seaking", + Pokemon.STARYU: "Staryu", + Pokemon.STARMIE: "Starmie", + Pokemon.MR_MIME: "Mr. Mime", + Pokemon.SCYTHER: "Scyther", + Pokemon.JYNX: "Jynx", + Pokemon.ELECTABUZZ: "Electabuzz", + Pokemon.MAGMAR: "Magmar", + Pokemon.PINSIR: "Pinsir", + Pokemon.TAUROS: "Tauros", + Pokemon.MAGIKARP: "Magikarp", + Pokemon.GYARADOS: "Gyarados", + Pokemon.LAPRAS: "Lapras", + Pokemon.DITTO: "Ditto", + Pokemon.EEVEE: "Eevee", + Pokemon.VAPOREON: "Vaporeon", + Pokemon.JOLTEON: "Jolteon", + Pokemon.FLAREON: "Flareon", + Pokemon.PORYGON: "Porygon", + Pokemon.OMANYTE: "Omanyte", + Pokemon.OMASTAR: "Omastar", + Pokemon.KABUTO: "Kabuto", + Pokemon.KABUTOPS: "Kabutops", + Pokemon.AERODACTYL: "Aerodactyl", + Pokemon.SNORLAX: "Snorlax", + Pokemon.ARTICUNO: "Articuno", + Pokemon.ZAPDOS: "Zapdos", + Pokemon.MOLTRES: "Moltres", + Pokemon.DRATINI: "Dratini", + Pokemon.DRAGONAIR: "Dragonair", + Pokemon.DRAGONITE: "Dragonite", + Pokemon.MEWTWO: "Mewtwo", + Pokemon.MEW: "Mew", +} \ No newline at end of file From 84dc3e8a1037ecc5dcce9a5c8c645d55145da666 Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Mon, 6 Nov 2023 11:17:26 -0500 Subject: [PATCH 22/74] Restructure files to break down constants into smaller parts for readability/start adding intermediate classes so data chance underneath doesn't affect API calls --- .../game_wrapper_pokemon_gen1/constants.py | 657 +----------------- .../{ => core}/gen_1_memory_manager.pxd | 0 .../core/gen_1_memory_manager.py | 16 + .../pokemon.py} | 76 +- .../pokemon.py => data/pokemon/constants.py} | 4 +- .../data/pokemon/memory.py | 43 ++ .../game_wrapper_pokemon_gen1.pxd | 2 +- .../game_wrapper_pokemon_gen1.py | 2 +- 8 files changed, 76 insertions(+), 724 deletions(-) rename pyboy/plugins/game_wrapper_pokemon_gen1/{ => core}/gen_1_memory_manager.pxd (100%) create mode 100644 pyboy/plugins/game_wrapper_pokemon_gen1/core/gen_1_memory_manager.py rename pyboy/plugins/game_wrapper_pokemon_gen1/{gen_1_memory_manager.py => core/pokemon.py} (56%) rename pyboy/plugins/game_wrapper_pokemon_gen1/{constants/pokemon.py => data/pokemon/constants.py} (99%) create mode 100644 pyboy/plugins/game_wrapper_pokemon_gen1/data/pokemon/memory.py diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py b/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py index c33c923e0..770fcea22 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py @@ -169,198 +169,6 @@ class Moves(Enum): SLASH = 0xa3 SUBSTITUTE = 0xa4 -class Pokemon(Enum): - RHYDON = 0x01 - KANGASKHAN = 0x02 - NIDORAN_M = 0x03 - CLEFAIRY = 0x04 - SPEAROW = 0x05 - VOLTORB = 0x06 - NIDOKING = 0x07 - SLOWBRO = 0x08 - IVYSAUR = 0x09 - EXEGGUTOR = 0x0A - LICKITUNG = 0x0B - EXEGGCUTE = 0x0C - GRIMER = 0x0D - GENGAR = 0x0E - NIDORAN_F = 0x0F - NIDOQUEEN = 0x10 - CUBONE = 0x11 - RHYHORN = 0x12 - LAPRAS = 0x13 - ARCANINE = 0x14 - MEW = 0x15 - GYARADOS = 0x16 - SHELLDER = 0x17 - TENTACOOL = 0x18 - GASTLY = 0x19 - SCYTHER = 0x1A - STARYU = 0x1B - BLASTOISE = 0x1C - PINSIR = 0x1D - TANGELA = 0x1E - MISSINGNO_1F = 0x1F - MISSINGNO_20 = 0x20 - GROWLITHE = 0x21 - ONIX = 0x22 - FEAROW = 0x23 - PIDGEY = 0x24 - SLOWPOKE = 0x25 - KADABRA = 0x26 - GRAVELER = 0x27 - CHANSEY = 0x28 - MACHOKE = 0x29 - MR_MIME = 0x2A - HITMONLEE = 0x2B - HITMONCHAN = 0x2C - ARBOK = 0x2D - PARASECT = 0x2E - PSYDUCK = 0x2F - DROWZEE = 0x30 - GOLEM = 0x31 - MISSINGNO_32 = 0x32 - MAGMAR = 0x33 - MISSINGNO_34 = 0x34 - ELECTABUZZ = 0x35 - MAGNETON = 0x36 - KOFFING = 0x37 - MISSINGNO_38 = 0x38 - MANKEY = 0x39 - SEEL = 0x3A - DIGLETT = 0x3B - TAUROS = 0x3C - MISSINGNO_3D = 0x3D - MISSINGNO_3E = 0x3E - MISSINGNO_3F = 0x3F - FARFETCHD = 0x40 - VENONAT = 0x41 - DRAGONITE = 0x42 - MISSINGNO_43 = 0x43 - MISSINGNO_44 = 0x44 - MISSINGNO_45 = 0x45 - DODUO = 0x46 - POLIWAG = 0x47 - JYNX = 0x48 - MOLTRES = 0x49 - ARTICUNO = 0x4A - ZAPDOS = 0x4B - DITTO = 0x4C - MEOWTH = 0x4D - KRABBY = 0x4E - MISSINGNO_4F = 0x4F - MISSINGNO_50 = 0x50 - MISSINGNO_51 = 0x51 - VULPIX = 0x52 - NINETALES = 0x53 - PIKACHU = 0x54 - RAICHU = 0x55 - MISSINGNO_56 = 0x56 - MISSINGNO_57 = 0x57 - DRATINI = 0x58 - DRAGONAIR = 0x59 - KABUTO = 0x5A - KABUTOPS = 0x5B - HORSEA = 0x5C - SEADRA = 0x5D - MISSINGNO_5E = 0x5E - MISSINGNO_5F = 0x5F - SANDSHREW = 0x60 - SANDSLASH = 0x61 - OMANYTE = 0x62 - OMASTAR = 0x63 - JIGGLYPUFF = 0x64 - WIGGLYTUFF = 0x65 - EEVEE = 0x66 - FLAREON = 0x67 - JOLTEON = 0x68 - VAPOREON = 0x69 - MACHOP = 0x6A - ZUBAT = 0x6B - EKANS = 0x6C - PARAS = 0x6D - POLIWHIRL = 0x6E - POLIWRATH = 0x6F - WEEDLE = 0x70 - KAKUNA = 0x71 - BEEDRILL = 0x72 - MISSINGNO_73 = 0x73 - DODRIO = 0x74 - PRIMEAPE = 0x75 - DUGTRIO = 0x76 - VENOMOTH = 0x77 - DEWGONG = 0x78 - MISSINGNO_79 = 0x79 - MISSINGNO_7A = 0x7A - CATERPIE = 0x7B - METAPOD = 0x7C - BUTTERFREE = 0x7D - MACHAMP = 0x7E - MISSINGNO_7F = 0x7F - GOLDUCK = 0x80 - HYPNO = 0x81 - GOLBAT = 0x82 - MEWTWO = 0x83 - SNORLAX = 0x84 - MAGIKARP = 0x85 - MISSINGNO_86 = 0x86 - MISSINGNO_87 = 0x87 - MUK = 0x88 - MISSINGNO_89 = 0x89 - KINGLER = 0x8A - CLOYSTER = 0x8B - MISSINGNO_8C = 0x8C - ELECTRODE = 0x8D - CLEFABLE = 0x8E - WEEZING = 0x8F - PERSIAN = 0x90 - MAROWAK = 0x91 - MISSINGNO_92 = 0x92 - HAUNTER = 0x93 - ABRA = 0x94 - ALAKAZAM = 0x95 - PIDGEOTTO = 0x96 - PIDGEOT = 0x97 - STARMIE = 0x98 - BULBASAUR = 0x99 - VENUSAUR = 0x9A - TENTACRUEL = 0x9B - MISSINGNO_9C = 0x9C - GOLDEEN = 0x9D - SEAKING = 0x9E - MISSINGNO_9F = 0x9F - MISSINGNO_A0 = 0xA0 - MISSINGNO_A1 = 0xA1 - MISSINGNO_A2 = 0xA2 - PONYTA = 0xA3 - RAPIDASH = 0xA4 - RATTATA = 0xA5 - RATICATE = 0xA6 - NIDORINO = 0xA7 - NIDORINA = 0xA8 - GEODUDE = 0xA9 - PORYGON = 0xAA - AERODACTYL = 0xAB - MISSINGNO_AC = 0xAC - MAGNEMITE = 0xAD - MISSINGNO_AE = 0xAE - MISSINGNO_AF = 0xAF - CHARMANDER = 0xB0 - SQUIRTLE = 0xB1 - CHARMELEON = 0xB2 - WARTORTLE = 0xB3 - CHARIZARD = 0xB4 - MISSINGNO_B5 = 0xB5 - FOSSIL_KABUTOPS = 0xB6 - FOSSIL_AERODACTYL = 0xB7 - MON_GHOST = 0xB8 - ODDISH = 0xB9 - GLOOM = 0xBA - VILEPLUME = 0xBB - BELLSPROUT = 0xBC - WEEPINBELL = 0xBD - VICTREEBEL = 0xBE - class Items(Enum): MASTER_BALL = 0x01 ULTRA_BALL = 0x02 @@ -1095,467 +903,4 @@ class Statuses(Enum): POISONED = 8 BURNED = 16 FROZEN = 32 - PARALYZED = 64 - -NAMES = ( - "Bulbasaur", - "Ivysaur", - "Venusaur", - "Charmander", - "Charmeleon", - "Charizard", - "Squirtle", - "Wartortle", - "Blastoise", - "Caterpie", - "Metapod", - "Butterfree", - "Weedle", - "Kakuna", - "Beedrill", - "Pidgey", - "Pidgeotto", - "Pidgeot", - "Rattata", - "Raticate", - "Spearow", - "Fearow", - "Ekans", - "Arbok", - "Pikachu", - "Raichu", - "Sandshrew", - "Sandslash", - "Nidoran♀", - "Nidorina", - "Nidoqueen", - "Nidoran♂", - "Nidorino", - "Nidoking", - "Clefairy", - "Clefable", - "Vulpix", - "Ninetales", - "Jigglypuff", - "Wigglytuff", - "Zubat", - "Golbat", - "Oddish", - "Gloom", - "Vileplume", - "Paras", - "Parasect", - "Venonat", - "Venomoth", - "Diglett", - "Dugtrio", - "Meowth", - "Persian", - "Psyduck", - "Golduck", - "Mankey", - "Primeape", - "Growlithe", - "Arcanine", - "Poliwag", - "Poliwhirl", - "Poliwrath", - "Abra", - "Kadabra", - "Alakazam", - "Machop", - "Machoke", - "Machamp", - "Bellsprout", - "Weepinbell", - "Victreebel", - "Tentacool", - "Tentacruel", - "Geodude", - "Graveler", - "Golem", - "Ponyta", - "Rapidash", - "Slowpoke", - "Slowbro", - "Magnemite", - "Magneton", - "Farfetch’d", - "Doduo", - "Dodrio", - "Seel", - "Dewgong", - "Grimer", - "Muk", - "Shellder", - "Cloyster", - "Gastly", - "Haunter", - "Gengar", - "Onix", - "Drowzee", - "Hypno", - "Krabby", - "Kingler", - "Voltorb", - "Electrode", - "Exeggcute", - "Exeggutor", - "Cubone", - "Marowak", - "Hitmonlee", - "Hitmonchan", - "Lickitung", - "Koffing", - "Weezing", - "Rhyhorn", - "Rhydon", - "Chansey", - "Tangela", - "Kangaskhan", - "Horsea", - "Seadra", - "Goldeen", - "Seaking", - "Staryu", - "Starmie", - "Mr. Mime", - "Scyther", - "Jynx", - "Electabuzz", - "Magmar", - "Pinsir", - "Tauros", - "Magikarp", - "Gyarados", - "Lapras", - "Ditto", - "Eevee", - "Vaporeon", - "Jolteon", - "Flareon", - "Porygon", - "Omanyte", - "Omastar", - "Kabuto", - "Kabutops", - "Aerodactyl", - "Snorlax", - "Articuno", - "Zapdos", - "Moltres", - "Dratini", - "Dragonair", - "Dragonite", - "Mewtwo", - "Mew", -) - -POKEMON_POKEDEX_INDEX = { - Pokemon.BULBASAUR: 1, - Pokemon.IVYSAUR: 2, - Pokemon.VENUSAUR: 3, - Pokemon.CHARMANDER: 4, - Pokemon.CHARMELEON: 5, - Pokemon.CHARIZARD: 6, - Pokemon.SQUIRTLE: 7, - Pokemon.WARTORTLE: 8, - Pokemon.BLASTOISE: 9, - Pokemon.CATERPIE: 10, - Pokemon.METAPOD: 11, - Pokemon.BUTTERFREE: 12, - Pokemon.WEEDLE: 13, - Pokemon.KAKUNA: 14, - Pokemon.BEEDRILL: 15, - Pokemon.PIDGEY: 16, - Pokemon.PIDGEOTTO: 17, - Pokemon.PIDGEOT: 18, - Pokemon.RATTATA: 19, - Pokemon.RATICATE: 20, - Pokemon.SPEAROW: 21, - Pokemon.FEAROW: 22, - Pokemon.EKANS: 23, - Pokemon.ARBOK: 24, - Pokemon.PIKACHU: 25, - Pokemon.RAICHU: 26, - Pokemon.SANDSHREW: 27, - Pokemon.SANDSLASH: 28, - Pokemon.NIDORAN_F: 29, - Pokemon.NIDORINA: 30, - Pokemon.NIDOQUEEN: 31, - Pokemon.NIDORAN_M: 32, - Pokemon.NIDORINO: 33, - Pokemon.NIDOKING: 34, - Pokemon.CLEFAIRY: 35, - Pokemon.CLEFABLE: 36, - Pokemon.VULPIX: 37, - Pokemon.NINETALES: 38, - Pokemon.JIGGLYPUFF: 39, - Pokemon.WIGGLYTUFF: 40, - Pokemon.ZUBAT: 41, - Pokemon.GOLBAT: 42, - Pokemon.ODDISH: 43, - Pokemon.GLOOM: 44, - Pokemon.VILEPLUME: 45, - Pokemon.PARAS: 46, - Pokemon.PARASECT: 47, - Pokemon.VENONAT: 48, - Pokemon.VENOMOTH: 49, - Pokemon.DIGLETT: 50, - Pokemon.DUGTRIO: 51, - Pokemon.MEOWTH: 52, - Pokemon.PERSIAN: 53, - Pokemon.PSYDUCK: 54, - Pokemon.GOLDUCK: 55, - Pokemon.MANKEY: 56, - Pokemon.PRIMEAPE: 57, - Pokemon.GROWLITHE: 58, - Pokemon.ARCANINE: 59, - Pokemon.POLIWAG: 60, - Pokemon.POLIWHIRL: 61, - Pokemon.POLIWRATH: 62, - Pokemon.ABRA: 63, - Pokemon.KADABRA: 64, - Pokemon.ALAKAZAM: 65, - Pokemon.MACHOP: 66, - Pokemon.MACHOKE: 67, - Pokemon.MACHAMP: 68, - Pokemon.BELLSPROUT: 69, - Pokemon.WEEPINBELL: 70, - Pokemon.VICTREEBEL: 71, - Pokemon.TENTACOOL: 72, - Pokemon.TENTACRUEL: 73, - Pokemon.GEODUDE: 74, - Pokemon.GRAVELER: 75, - Pokemon.GOLEM: 76, - Pokemon.PONYTA: 77, - Pokemon.RAPIDASH: 78, - Pokemon.SLOWPOKE: 79, - Pokemon.SLOWBRO: 80, - Pokemon.MAGNEMITE: 81, - Pokemon.MAGNETON: 82, - Pokemon.FARFETCHD: 83, - Pokemon.DODUO: 84, - Pokemon.DODRIO: 85, - Pokemon.SEEL: 86, - Pokemon.DEWGONG: 87, - Pokemon.GRIMER: 88, - Pokemon.MUK: 89, - Pokemon.SHELLDER: 90, - Pokemon.CLOYSTER: 91, - Pokemon.GASTLY: 92, - Pokemon.HAUNTER: 93, - Pokemon.GENGAR: 94, - Pokemon.ONIX: 95, - Pokemon.DROWZEE: 96, - Pokemon.HYPNO: 97, - Pokemon.KRABBY: 98, - Pokemon.KINGLER: 99, - Pokemon.VOLTORB: 100, - Pokemon.ELECTRODE: 101, - Pokemon.EXEGGCUTE: 102, - Pokemon.EXEGGUTOR: 103, - Pokemon.CUBONE: 104, - Pokemon.MAROWAK: 105, - Pokemon.HITMONLEE: 106, - Pokemon.HITMONCHAN: 107, - Pokemon.LICKITUNG: 108, - Pokemon.KOFFING: 109, - Pokemon.WEEZING: 110, - Pokemon.RHYHORN: 111, - Pokemon.RHYDON: 112, - Pokemon.CHANSEY: 113, - Pokemon.TANGELA: 114, - Pokemon.KANGASKHAN: 115, - Pokemon.HORSEA: 116, - Pokemon.SEADRA: 117, - Pokemon.GOLDEEN: 118, - Pokemon.SEAKING: 119, - Pokemon.STARYU: 120, - Pokemon.STARMIE: 121, - Pokemon.MR_MIME: 122, - Pokemon.SCYTHER: 123, - Pokemon.JYNX: 124, - Pokemon.ELECTABUZZ: 125, - Pokemon.MAGMAR: 126, - Pokemon.PINSIR: 127, - Pokemon.TAUROS: 128, - Pokemon.MAGIKARP: 129, - Pokemon.GYARADOS: 130, - Pokemon.LAPRAS: 131, - Pokemon.DITTO: 132, - Pokemon.EEVEE: 133, - Pokemon.VAPOREON: 134, - Pokemon.JOLTEON: 135, - Pokemon.FLAREON: 136, - Pokemon.PORYGON: 137, - Pokemon.OMANYTE: 138, - Pokemon.OMASTAR: 139, - Pokemon.KABUTO: 140, - Pokemon.KABUTOPS: 141, - Pokemon.AERODACTYL: 142, - Pokemon.SNORLAX: 143, - Pokemon.ARTICUNO: 144, - Pokemon.ZAPDOS: 145, - Pokemon.MOLTRES: 146, - Pokemon.DRATINI: 147, - Pokemon.DRAGONAIR: 148, - Pokemon.DRAGONITE: 149, - Pokemon.MEWTWO: 150, - Pokemon.MEW: 151 -} - - -POKEDEX_TO_INDEX_MAP = ( - (112, 0x01), - (115, 0x02), - (32, 0x03), - (35, 0x04), - (21, 0x05), - (100, 0x06), - (34, 0x07), - (80, 0x08), - (2, 0x09), - (103, 0x0A), - (108, 0x0B), - (102, 0x0C), - (88, 0x0D), - (94, 0x0E), - (29, 0x0F), - (31, 0x10), - (104, 0x11), - (111, 0x12), - (131, 0x13), - (59, 0x14), - (151, 0x15), - (130, 0x16), - (90, 0x17), - (72, 0x18), - (92, 0x19), - (123, 0x1A), - (120, 0x1B), - (9, 0x1C), - (127, 0x1D), - (114, 0x1E), - (58, 0x21), - (95, 0x22), - (22, 0x23), - (16, 0x24), - (79, 0x25), - (64, 0x26), - (75, 0x27), - (113, 0x28), - (67, 0x29), - (122, 0x2A), - (106, 0x2B), - (107, 0x2C), - (24, 0x2D), - (47, 0x2E), - (54, 0x2F), - (96, 0x30), - (76, 0x31), - (126, 0x33), - (125, 0x35), - (82, 0x36), - (109, 0x37), - (56, 0x39), - (86, 0x3A), - (50, 0x3B), - (128, 0x3C), - (83, 0x40), - (48, 0x41), - (149, 0x42), - (84, 0x46), - (60, 0x47), - (124, 0x48), - (146, 0x49), - (144, 0x4A), - (145, 0x4B), - (132, 0x4C), - (52, 0x4D), - (98, 0x4E), - (37, 0x52), - (38, 0x53), - (25, 0x54), - (26, 0x55), - (147, 0x58), - (148, 0x59), - (140, 0x5A), - (141, 0x5B), - (116, 0x5C), - (117, 0x5D), - (27, 0x60), - (28, 0x61), - (138, 0x62), - (139, 0x63), - (39, 0x64), - (40, 0x65), - (133, 0x66), - (136, 0x67), - (135, 0x68), - (134, 0x69), - (66, 0x6A), - (41, 0x6B), - (23, 0x6C), - (46, 0x6D), - (61, 0x6E), - (62, 0x6F), - (13, 0x70), - (14, 0x71), - (15, 0x72), - (85, 0x74), - (57, 0x75), - (51, 0x76), - (49, 0x77), - (87, 0x78), - (10, 0x7B), - (11, 0x7C), - (12, 0x7D), - (68, 0x7E), - (55, 0x80), - (97, 0x81), - (42, 0x82), - (150, 0x83), - (143, 0x84), - (129, 0x85), - (89, 0x88), - (99, 0x8A), - (91, 0x8B), - (101, 0x8D), - (36, 0x8E), - (110, 0x8F), - (53, 0x90), - (105, 0x91), - (93, 0x93), - (63, 0x94), - (65, 0x95), - (17, 0x96), - (18, 0x97), - (121, 0x98), - (1, 0x99), - (2, 0x9A), - (73, 0x9B), - (118, 0x9D), - (119, 0x9E), - (77, 0xA3), - (78, 0xA4), - (19, 0xA5), - (20, 0xA6), - (33, 0xA7), - (30, 0xA8), - (74, 0xA9), - (137, 0xAA), - (142, 0xAB), - (81, 0xAD), - (4, 0xB0), - (7, 0xB1), - (5, 0xB2), - (8, 0xB3), - (6, 0xB4), - (43, 0xB9), - (44, 0xBA), - (45, 0xBB), - (69, 0xBC), - (70, 0xBD), - (71, 0xBE), -) + PARALYZED = 64 \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/gen_1_memory_manager.pxd b/pyboy/plugins/game_wrapper_pokemon_gen1/core/gen_1_memory_manager.pxd similarity index 100% rename from pyboy/plugins/game_wrapper_pokemon_gen1/gen_1_memory_manager.pxd rename to pyboy/plugins/game_wrapper_pokemon_gen1/core/gen_1_memory_manager.pxd diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/gen_1_memory_manager.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/gen_1_memory_manager.py new file mode 100644 index 000000000..433054cc7 --- /dev/null +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/gen_1_memory_manager.py @@ -0,0 +1,16 @@ +from .pokemon import Pokemon + +# All info from https://datacrystal.romhacking.net/wiki/Pok%C3%A9mon_Red/Blue:RAM_map#ROM_banking + +SRAM = (0xA000, 0xBFFF) +WRAM = (0xC000, 0xDFFF) # Unsure of where this range ACTUALLY ends +HRAM = (0xFF80, 0xFFFE) + +class Gen1MemoryManager: + + def __init__(self, pyboy, byte_order='big'): + self.pyboy = pyboy + self.byte_order = byte_order + + def load_pokemon_from_party(self, party_location): + return Pokemon.load_pokemon_from_party(self.pyboy, party_location) \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/gen_1_memory_manager.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py similarity index 56% rename from pyboy/plugins/game_wrapper_pokemon_gen1/gen_1_memory_manager.py rename to pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py index b2a6aab1c..308e92292 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/gen_1_memory_manager.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py @@ -1,52 +1,4 @@ -from enum import Enum - -# All info from https://datacrystal.romhacking.net/wiki/Pok%C3%A9mon_Red/Blue:RAM_map#ROM_banking - -SRAM = (0xA000, 0xBFFF) -WRAM = (0xC000, 0xDFFF) # Unsure of where this range ACTUALLY ends -HRAM = (0xFF80, 0xFFFE) - -# Pokemon locations in memory -class PokemonBaseAddrs(Enum): - POKEMON_1 = 0xD16B - POKEMON_2 = 0xD197 - POKEMON_3 = 0xD1C3 - POKEMON_4 = 0xD1EF - POKEMON_5 = 0xD21B - POKEMON_6 = 0xD247 - -# Offsets for Pokemon data access -# Structure is (offset, num bytes) -class PokemonOffsets(Enum): - ID = (0x0, 1) - CURRENT_HP = (0x1, 2) - STATUS = (0x3, 1) - TYPE_1 = (0x4, 1) - TYPE_2 = (0x5, 1) - CATCH_RATE = (0x6, 1) - MOVE_1 = (0x7, 1) - MOVE_2 = (0x8, 1) - MOVE_3 = (0x9, 1) - MOVE_4 = (0xA, 1) - TRAINER_ID = (0xB, 2) - EXPERIENCE = (0xD, 3) - HP_EV = (0x11, 2) - ATTACK_EV = (0x13, 2) - DEFENSE_EV = (0x15, 2) - SPEED_EV = (0x17, 2) - SPECIAL_EV = (0x19, 2) - ATTACK_DEFENSE_IV = (0x1B, 1) - SPEED_SPECIAL_IV = (0x1C, 1) - PP_MOVE_1 = (0x1D, 1) - PP_MOVE_2 = (0x1E, 1) - PP_MOVE_3 = (0x1F, 1) - PP_MOVE_4 = (0x20, 1) - LEVEL = (0x21, 1) - MAX_HP = (0x22, 2) - ATTACK = (0x24, 2) - DEFENSE = (0x26, 2) - SPEED = (0x28, 2) - SPECIAL = (0x2A, 2) +from ..data.pokemon.memory import PokemonBaseAddrs, PokemonOffsets class Pokemon: @@ -110,29 +62,25 @@ def __init__(self, self.speed = speed self.special = special - def pretty_stringify(self): - s = ''' - - ''' - -class Gen1MemoryManager: - - def __init__(self, pyboy, byte_order='big'): - self.pyboy = pyboy - self.byte_order = byte_order - - def _load_pokemon_from_address(self, pokemon_base_address): + @classmethod + def _load_pokemon_from_address(self, pyboy, pokemon_base_address): pokemon_values = [] for offset_enum in PokemonOffsets: offset, num_bytes = offset_enum.value[0], offset_enum.value[1] - memory_value = self.pyboy.get_memory_value(pokemon_base_address+offset, num_bytes) + memory_value = pyboy.get_memory_value(pokemon_base_address+offset, num_bytes) pokemon_values.append(memory_value) return Pokemon(*pokemon_values) - def load_pokemon_from_party(self, party_location): + @classmethod + def load_pokemon_from_party(self, pyboy, party_location): # party_location goes from 1 to 6 pokemon_base_address = list(PokemonBaseAddrs)[party_location-1].value - return self._load_pokemon_from_address(pokemon_base_address) \ No newline at end of file + return self._load_pokemon_from_address(pyboy, pokemon_base_address) + + def pretty_stringify(self): + s = ''' + + ''' \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/constants/pokemon.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/pokemon/constants.py similarity index 99% rename from pyboy/plugins/game_wrapper_pokemon_gen1/constants/pokemon.py rename to pyboy/plugins/game_wrapper_pokemon_gen1/data/pokemon/constants.py index 3655cc5c1..c3d46ae5e 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/constants/pokemon.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/pokemon/constants.py @@ -192,7 +192,7 @@ class Pokemon(Enum): WEEPINBELL = 0xBD VICTREEBEL = 0xBE -POKEMON_POKEDEX_INDEX = { +_POKEMON_POKEDEX_INDEX = { Pokemon.BULBASAUR: 1, Pokemon.IVYSAUR: 2, Pokemon.VENUSAUR: 3, @@ -346,7 +346,7 @@ class Pokemon(Enum): Pokemon.MEW: 151 } -POKEMON_NAMES = { +_POKEMON_NAMES = { Pokemon.BULBASAUR: "Bulbasaur", Pokemon.IVYSAUR: "Ivysaur", Pokemon.VENUSAUR: "Venusaur", diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/pokemon/memory.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/pokemon/memory.py new file mode 100644 index 000000000..62adc7806 --- /dev/null +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/pokemon/memory.py @@ -0,0 +1,43 @@ +# Pokemon locations in memory +from enum import Enum + +class PokemonBaseAddrs(Enum): + POKEMON_1 = 0xD16B + POKEMON_2 = 0xD197 + POKEMON_3 = 0xD1C3 + POKEMON_4 = 0xD1EF + POKEMON_5 = 0xD21B + POKEMON_6 = 0xD247 + +# Offsets for Pokemon data access +# Structure is (offset, num bytes) +class PokemonOffsets(Enum): + ID = (0x0, 1) + CURRENT_HP = (0x1, 2) + STATUS = (0x3, 1) + TYPE_1 = (0x4, 1) + TYPE_2 = (0x5, 1) + CATCH_RATE = (0x6, 1) + MOVE_1 = (0x7, 1) + MOVE_2 = (0x8, 1) + MOVE_3 = (0x9, 1) + MOVE_4 = (0xA, 1) + TRAINER_ID = (0xB, 2) + EXPERIENCE = (0xD, 3) + HP_EV = (0x11, 2) + ATTACK_EV = (0x13, 2) + DEFENSE_EV = (0x15, 2) + SPEED_EV = (0x17, 2) + SPECIAL_EV = (0x19, 2) + ATTACK_DEFENSE_IV = (0x1B, 1) + SPEED_SPECIAL_IV = (0x1C, 1) + PP_MOVE_1 = (0x1D, 1) + PP_MOVE_2 = (0x1E, 1) + PP_MOVE_3 = (0x1F, 1) + PP_MOVE_4 = (0x20, 1) + LEVEL = (0x21, 1) + MAX_HP = (0x22, 2) + ATTACK = (0x24, 2) + DEFENSE = (0x26, 2) + SPEED = (0x28, 2) + SPECIAL = (0x2A, 2) \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.pxd b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.pxd index 41bd6bdb1..3842a2374 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.pxd +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.pxd @@ -4,7 +4,7 @@ # from libc.stdint cimport uint8_t from pyboy.plugins.base_plugin cimport PyBoyGameWrapper -from pyboy.plugins.game_wrapper_pokemon_gen1.gen_1_memory_manager cimport Gen1MemoryManager +from pyboy.plugins.game_wrapper_pokemon_gen1.core.gen_1_memory_manager cimport Gen1MemoryManager cimport cython cdef class GameWrapperPokemonGen1(PyBoyGameWrapper): diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py index e83e3b6ce..a17e5099a 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py @@ -12,7 +12,7 @@ from pyboy.utils import WindowEvent from pyboy.logger import logger from ..base_plugin import PyBoyGameWrapper -from .gen_1_memory_manager import Gen1MemoryManager +from .core.gen_1_memory_manager import Gen1MemoryManager from . import constants from .utils import get_character_index From 4cba7bafe013d68c15ed0c9cfbbf0a9eba58fec3 Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Mon, 6 Nov 2023 12:00:34 -0500 Subject: [PATCH 23/74] Move location constants into new directory and create dict for name lookup --- .../data/locations/constants.py | 502 ++++++++++++++++++ 1 file changed, 502 insertions(+) create mode 100644 pyboy/plugins/game_wrapper_pokemon_gen1/data/locations/constants.py diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/locations/constants.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/locations/constants.py new file mode 100644 index 000000000..b7c5af7e8 --- /dev/null +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/locations/constants.py @@ -0,0 +1,502 @@ +from enum import Enum + +class Locations(Enum): + PALLET_TOWN = 0x00 + VIRIDIAN_CITY = 0x01 + PEWTER_CITY = 0x02 + CERULEAN_CITY = 0x03 + LAVENDER_TOWN = 0x04 + VERMILION_CITY = 0x05 + CELADON_CITY = 0x06 + FUCHSIA_CITY = 0x07 + CINNABAR_ISLAND = 0x08 + INDIGO_PLATEAU = 0x09 + SAFFRON_CITY = 0x0A + UNUSED_MAP_0B = 0x0B + ROUTE_1 = 0x0C + ROUTE_2 = 0x0D + ROUTE_3 = 0x0E + ROUTE_4 = 0x0F + ROUTE_5 = 0x10 + ROUTE_6 = 0x11 + ROUTE_7 = 0x12 + ROUTE_8 = 0x13 + ROUTE_9 = 0x14 + ROUTE_10 = 0x15 + ROUTE_11 = 0x16 + ROUTE_12 = 0x17 + ROUTE_13 = 0x18 + ROUTE_14 = 0x19 + ROUTE_15 = 0x1A + ROUTE_16 = 0x1B + ROUTE_17 = 0x1C + ROUTE_18 = 0x1D + ROUTE_19 = 0x1E + ROUTE_20 = 0x1F + ROUTE_21 = 0x20 + ROUTE_22 = 0x21 + ROUTE_23 = 0x22 + ROUTE_24 = 0x23 + ROUTE_25 = 0x24 + REDS_HOUSE_1F = 0x25 + REDS_HOUSE_2F = 0x26 + BLUES_HOUSE = 0x27 + OAKS_LAB = 0x28 + VIRIDIAN_POKECENTER = 0x29 + VIRIDIAN_MART = 0x2A + VIRIDIAN_SCHOOL_HOUSE = 0x2B + VIRIDIAN_NICKNAME_HOUSE = 0x2C + VIRIDIAN_GYM = 0x2D + DIGLETTS_CAVE_ROUTE_2 = 0x2E + VIRIDIAN_FOREST_NORTH_GATE = 0x2F + ROUTE_2_TRADE_HOUSE = 0x30 + ROUTE_2_GATE = 0x31 + VIRIDIAN_FOREST_SOUTH_GATE = 0x32 + VIRIDIAN_FOREST = 0x33 + MUSEUM_1F = 0x34 + MUSEUM_2F = 0x35 + PEWTER_GYM = 0x36 + PEWTER_NIDORAN_HOUSE = 0x37 + PEWTER_MART = 0x38 + PEWTER_SPEECH_HOUSE = 0x39 + PEWTER_POKECENTER = 0x3A + MT_MOON_1F = 0x3B + MT_MOON_B1F = 0x3C + MT_MOON_B2F = 0x3D + CERULEAN_TRASHED_HOUSE = 0x3E + CERULEAN_TRADE_HOUSE = 0x3F + CERULEAN_POKECENTER = 0x40 + CERULEAN_GYM = 0x41 + BIKE_SHOP = 0x42 + CERULEAN_MART = 0x43 + MT_MOON_POKECENTER = 0x44 + CERULEAN_TRASHED_HOUSE_COPY = 0x45 + ROUTE_5_GATE = 0x46 + UNDERGROUND_PATH_ROUTE_5 = 0x47 + DAYCARE = 0x48 + ROUTE_6_GATE = 0x49 + UNDERGROUND_PATH_ROUTE_6 = 0x4A + UNDERGROUND_PATH_ROUTE_6_COPY = 0x4B + ROUTE_7_GATE = 0x4C + UNDERGROUND_PATH_ROUTE_7 = 0x4D + UNDERGROUND_PATH_ROUTE_7_COPY = 0x4E + ROUTE_8_GATE = 0x4F + UNDERGROUND_PATH_ROUTE_8 = 0x50 + ROCK_TUNNEL_POKECENTER = 0x51 + ROCK_TUNNEL_1F = 0x52 + POWER_PLANT = 0x53 + ROUTE_11_GATE_1F = 0x54 + DIGLETTS_CAVE_ROUTE_11 = 0x55 + ROUTE_11_GATE_2F = 0x56 + ROUTE_12_GATE_1F = 0x57 + BILLS_HOUSE = 0x58 + VERMILION_POKECENTER = 0x59 + POKEMON_FAN_CLUB = 0x5A + VERMILION_MART = 0x5B + VERMILION_GYM = 0x5C + VERMILION_PIDGEY_HOUSE = 0x5D + VERMILION_DOCK = 0x5E + SS_ANNE_1F = 0x5F + SS_ANNE_2F = 0x60 + SS_ANNE_3F = 0x61 + SS_ANNE_B1F = 0x62 + SS_ANNE_BOW = 0x63 + SS_ANNE_KITCHEN = 0x64 + SS_ANNE_CAPTAINS_ROOM = 0x65 + SS_ANNE_1F_ROOMS = 0x66 + SS_ANNE_2F_ROOMS = 0x67 + SS_ANNE_B1F_ROOMS = 0x68 + UNUSED_MAP_69 = 0x69 + UNUSED_MAP_6A = 0x6A + UNUSED_MAP_6B = 0x6B + VICTORY_ROAD_1F = 0x6C + UNUSED_MAP_6D = 0x6D + UNUSED_MAP_6E = 0x6E + UNUSED_MAP_6F = 0x6F + UNUSED_MAP_70 = 0x70 + LANCES_ROOM = 0x71 + UNUSED_MAP_72 = 0x72 + UNUSED_MAP_73 = 0x73 + UNUSED_MAP_74 = 0x74 + UNUSED_MAP_75 = 0x75 + HALL_OF_FAME = 0x76 + UNDERGROUND_PATH_NORTH_SOUTH = 0x77 + CHAMPIONS_ROOM = 0x78 + UNDERGROUND_PATH_WEST_EAST = 0x79 + CELADON_MART_1F = 0x7A + CELADON_MART_2F = 0x7B + CELADON_MART_3F = 0x7C + CELADON_MART_4F = 0x7D + CELADON_MART_ROOF = 0x7E + CELADON_MART_ELEVATOR = 0x7F + CELADON_MANSION_1F = 0x80 + CELADON_MANSION_2F = 0x81 + CELADON_MANSION_3F = 0x82 + CELADON_MANSION_ROOF = 0x83 + CELADON_MANSION_ROOF_HOUSE = 0x84 + CELADON_POKECENTER = 0x85 + CELADON_GYM = 0x86 + GAME_CORNER = 0x87 + CELADON_MART_5F = 0x88 + GAME_CORNER_PRIZE_ROOM = 0x89 + CELADON_DINER = 0x8A + CELADON_CHIEF_HOUSE = 0x8B + CELADON_HOTEL = 0x8C + LAVENDER_POKECENTER = 0x8D + POKEMON_TOWER_1F = 0x8E + POKEMON_TOWER_2F = 0x8F + POKEMON_TOWER_3F = 0x90 + POKEMON_TOWER_4F = 0x91 + POKEMON_TOWER_5F = 0x92 + POKEMON_TOWER_6F = 0x93 + POKEMON_TOWER_7F = 0x94 + MR_FUJIS_HOUSE = 0x95 + LAVENDER_MART = 0x96 + LAVENDER_CUBONE_HOUSE = 0x97 + FUCHSIA_MART = 0x98 + FUCHSIA_BILLS_GRANDPAS_HOUSE = 0x99 + FUCHSIA_POKECENTER = 0x9A + WARDENS_HOUSE = 0x9B + SAFARI_ZONE_GATE = 0x9C + FUCHSIA_GYM = 0x9D + FUCHSIA_MEETING_ROOM = 0x9E + SEAFOAM_ISLANDS_B1F = 0x9F + SEAFOAM_ISLANDS_B2F = 0xA0 + SEAFOAM_ISLANDS_B3F = 0xA1 + SEAFOAM_ISLANDS_B4F = 0xA2 + VERMILION_OLD_ROD_HOUSE = 0xA3 + FUCHSIA_GOOD_ROD_HOUSE = 0xA4 + POKEMON_MANSION_1F = 0xA5 + CINNABAR_GYM = 0xA6 + CINNABAR_LAB = 0xA7 + CINNABAR_LAB_TRADE_ROOM = 0xA8 + CINNABAR_LAB_METRONOME_ROOM = 0xA9 + CINNABAR_LAB_FOSSIL_ROOM = 0xAA + CINNABAR_POKECENTER = 0xAB + CINNABAR_MART = 0xAC + CINNABAR_MART_COPY = 0xAD + INDIGO_PLATEAU_LOBBY = 0xAE + COPYCATS_HOUSE_1F = 0xAF + COPYCATS_HOUSE_2F = 0xB0 + FIGHTING_DOJO = 0xB1 + SAFFRON_GYM = 0xB2 + SAFFRON_PIDGEY_HOUSE = 0xB3 + SAFFRON_MART = 0xB4 + SILPH_CO_1F = 0xB5 + SAFFRON_POKECENTER = 0xB6 + MR_PSYCHICS_HOUSE = 0xB7 + ROUTE_15_GATE_1F = 0xB8 + ROUTE_15_GATE_2F = 0xB9 + ROUTE_16_GATE_1F = 0xBA + ROUTE_16_GATE_2F = 0xBB + ROUTE_16_FLY_HOUSE = 0xBC + ROUTE_12_SUPER_ROD_HOUSE = 0xBD + ROUTE_18_GATE_1F = 0xBE + ROUTE_18_GATE_2F = 0xBF + SEAFOAM_ISLANDS_1F = 0xC0 + ROUTE_22_GATE = 0xC1 + VICTORY_ROAD_2F = 0xC2 + ROUTE_12_GATE_2F = 0xC3 + VERMILION_TRADE_HOUSE = 0xC4 + DIGLETTS_CAVE = 0xC5 + VICTORY_ROAD_3F = 0xC6 + ROCKET_HIDEOUT_B1F = 0xC7 + ROCKET_HIDEOUT_B2F = 0xC8 + ROCKET_HIDEOUT_B3F = 0xC9 + ROCKET_HIDEOUT_B4F = 0xCA + ROCKET_HIDEOUT_ELEVATOR = 0xCB + UNUSED_MAP_CC = 0xCC + UNUSED_MAP_CD = 0xCD + UNUSED_MAP_CE = 0xCE + SILPH_CO_2F = 0xCF + SILPH_CO_3F = 0xD0 + SILPH_CO_4F = 0xD1 + SILPH_CO_5F = 0xD2 + SILPH_CO_6F = 0xD3 + SILPH_CO_7F = 0xD4 + SILPH_CO_8F = 0xD5 + POKEMON_MANSION_2F = 0xD6 + POKEMON_MANSION_3F = 0xD7 + POKEMON_MANSION_B1F = 0xD8 + SAFARI_ZONE_EAST = 0xD9 + SAFARI_ZONE_NORTH = 0xDA + SAFARI_ZONE_WEST = 0xDB + SAFARI_ZONE_CENTER = 0xDC + SAFARI_ZONE_CENTER_REST_HOUSE = 0xDD + SAFARI_ZONE_SECRET_HOUSE = 0xDE + SAFARI_ZONE_WEST_REST_HOUSE = 0xDF + SAFARI_ZONE_EAST_REST_HOUSE = 0xE0 + SAFARI_ZONE_NORTH_REST_HOUSE = 0xE1 + CERULEAN_CAVE_2F = 0xE2 + CERULEAN_CAVE_B1F = 0xE3 + CERULEAN_CAVE_1F = 0xE4 + NAME_RATERS_HOUSE = 0xE5 + CERULEAN_BADGE_HOUSE = 0xE6 + UNUSED_MAP_E7 = 0xE7 + ROCK_TUNNEL_B1F = 0xE8 + SILPH_CO_9F = 0xE9 + SILPH_CO_10F = 0xEA + SILPH_CO_11F = 0xEB + SILPH_CO_ELEVATOR = 0xEC + UNUSED_MAP_ED = 0xED + UNUSED_MAP_EE = 0xEE + TRADE_CENTER = 0xEF + COLOSSEUM = 0xF0 + UNUSED_MAP_F1 = 0xF1 + UNUSED_MAP_F2 = 0xF2 + UNUSED_MAP_F3 = 0xF3 + UNUSED_MAP_F4 = 0xF4 + LORELEIS_ROOM = 0xF5 + BRUNOS_ROOM = 0xF6 + AGATHAS_ROOM = 0xF7 + +LOCATION_NAMES = { + Locations.PALLET_TOWN: 'PALLET TOWN', + Locations.VIRIDIAN_CITY: 'VIRIDIAN CITY', + Locations.PEWTER_CITY: 'PEWTER CITY', + Locations.CERULEAN_CITY: 'CERULEAN CITY', + Locations.LAVENDER_TOWN: 'LAVENDER TOWN', + Locations.VERMILION_CITY: 'VERMILION CITY', + Locations.CELADON_CITY: 'CELADON CITY', + Locations.FUCHSIA_CITY: 'FUCHSIA CITY', + Locations.CINNABAR_ISLAND: 'CINNABAR ISLAND', + Locations.INDIGO_PLATEAU: 'INDIGO PLATEAU', + Locations.SAFFRON_CITY: 'SAFFRON CITY', + Locations.UNUSED_MAP_0B: 'UNUSED MAP 0B', + Locations.ROUTE_1: 'ROUTE 1', + Locations.ROUTE_2: 'ROUTE 2', + Locations.ROUTE_3: 'ROUTE 3', + Locations.ROUTE_4: 'ROUTE 4', + Locations.ROUTE_5: 'ROUTE 5', + Locations.ROUTE_6: 'ROUTE 6', + Locations.ROUTE_7: 'ROUTE 7', + Locations.ROUTE_8: 'ROUTE 8', + Locations.ROUTE_9: 'ROUTE 9', + Locations.ROUTE_10: 'ROUTE 10', + Locations.ROUTE_11: 'ROUTE 11', + Locations.ROUTE_12: 'ROUTE 12', + Locations.ROUTE_13: 'ROUTE 13', + Locations.ROUTE_14: 'ROUTE 14', + Locations.ROUTE_15: 'ROUTE 15', + Locations.ROUTE_16: 'ROUTE 16', + Locations.ROUTE_17: 'ROUTE 17', + Locations.ROUTE_18: 'ROUTE 18', + Locations.ROUTE_19: 'ROUTE 19', + Locations.ROUTE_20: 'ROUTE 20', + Locations.ROUTE_21: 'ROUTE 21', + Locations.ROUTE_22: 'ROUTE 22', + Locations.ROUTE_23: 'ROUTE 23', + Locations.ROUTE_24: 'ROUTE 24', + Locations.ROUTE_25: 'ROUTE 25', + Locations.REDS_HOUSE_1F: 'RED\'S HOUSE 1F', + Locations.REDS_HOUSE_2F: 'RED\'S HOUSE 2F', + Locations.BLUES_HOUSE: 'BLUE\'S HOUSE', + Locations.OAKS_LAB: 'OAK\'S LAB', + Locations.VIRIDIAN_POKECENTER: 'VIRIDIAN POKECENTER', + Locations.VIRIDIAN_MART: 'VIRIDIAN MART', + Locations.VIRIDIAN_SCHOOL_HOUSE: 'VIRIDIAN SCHOOL HOUSE', + Locations.VIRIDIAN_NICKNAME_HOUSE: 'VIRIDIAN NICKNAME HOUSE', + Locations.VIRIDIAN_GYM: 'VIRIDIAN GYM', + Locations.DIGLETTS_CAVE_ROUTE_2: 'DIGLETTS CAVE ROUTE 2', + Locations.VIRIDIAN_FOREST_NORTH_GATE: 'VIRIDIAN FOREST NORTH GATE', + Locations.ROUTE_2_TRADE_HOUSE: 'ROUTE 2 TRADE HOUSE', + Locations.ROUTE_2_GATE: 'ROUTE 2 GATE', + Locations.VIRIDIAN_FOREST_SOUTH_GATE: 'VIRIDIAN FOREST SOUTH GATE', + Locations.VIRIDIAN_FOREST: 'VIRIDIAN FOREST', + Locations.MUSEUM_1F: 'MUSEUM 1F', + Locations.MUSEUM_2F: 'MUSEUM 2F', + Locations.PEWTER_GYM: 'PEWTER GYM', + Locations.PEWTER_NIDORAN_HOUSE: 'PEWTER NIDORAN HOUSE', + Locations.PEWTER_MART: 'PEWTER MART', + Locations.PEWTER_SPEECH_HOUSE: 'PEWTER SPEECH HOUSE', + Locations.PEWTER_POKECENTER: 'PEWTER POKECENTER', + Locations.MT_MOON_1F: 'MT MOON 1F', + Locations.MT_MOON_B1F: 'MT MOON B1F', + Locations.MT_MOON_B2F: 'MT MOON B2F', + Locations.CERULEAN_TRASHED_HOUSE: 'CERULEAN TRASHED HOUSE', + Locations.CERULEAN_TRADE_HOUSE: 'CERULEAN TRADE HOUSE', + Locations.CERULEAN_POKECENTER: 'CERULEAN POKECENTER', + Locations.CERULEAN_GYM: 'CERULEAN GYM', + Locations.BIKE_SHOP: 'BIKE SHOP', + Locations.CERULEAN_MART: 'CERULEAN MART', + Locations.MT_MOON_POKECENTER: 'MT MOON POKECENTER', + Locations.CERULEAN_TRASHED_HOUSE_COPY: 'CERULEAN TRASHED HOUSE COPY', + Locations.ROUTE_5_GATE: 'ROUTE 5 GATE', + Locations.UNDERGROUND_PATH_ROUTE_5: 'UNDERGROUND PATH ROUTE 5', + Locations.DAYCARE: 'DAYCARE', + Locations.ROUTE_6_GATE: 'ROUTE 6 GATE', + Locations.UNDERGROUND_PATH_ROUTE_6: 'UNDERGROUND PATH ROUTE 6', + Locations.UNDERGROUND_PATH_ROUTE_6_COPY: 'UNDERGROUND PATH ROUTE 6 COPY', + Locations.ROUTE_7_GATE: 'ROUTE 7 GATE', + Locations.UNDERGROUND_PATH_ROUTE_7: 'UNDERGROUND PATH ROUTE 7', + Locations.UNDERGROUND_PATH_ROUTE_7_COPY: 'UNDERGROUND PATH ROUTE 7 COPY', + Locations.ROUTE_8_GATE: 'ROUTE 8 GATE', + Locations.UNDERGROUND_PATH_ROUTE_8: 'UNDERGROUND PATH ROUTE 8', + Locations.ROCK_TUNNEL_POKECENTER: 'ROCK TUNNEL POKECENTER', + Locations.ROCK_TUNNEL_1F: 'ROCK TUNNEL 1F', + Locations.POWER_PLANT: 'POWER PLANT', + Locations.ROUTE_11_GATE_1F: 'ROUTE 11 GATE 1F', + Locations.DIGLETTS_CAVE_ROUTE_11: 'DIGLETT\'S CAVE ROUTE 11', + Locations.ROUTE_11_GATE_2F: 'ROUTE 11 GATE 2F', + Locations.ROUTE_12_GATE_1F: 'ROUTE 12 GATE 1F', + Locations.BILLS_HOUSE: 'BILLS HOUSE', + Locations.VERMILION_POKECENTER: 'VERMILION POKECENTER', + Locations.POKEMON_FAN_CLUB: 'POKEMON FAN CLUB', + Locations.VERMILION_MART: 'VERMILION MART', + Locations.VERMILION_GYM: 'VERMILION GYM', + Locations.VERMILION_PIDGEY_HOUSE: 'VERMILION PIDGEY HOUSE', + Locations.VERMILION_DOCK: 'VERMILION DOCK', + Locations.SS_ANNE_1F: 'SS ANNE 1F', + Locations.SS_ANNE_2F: 'SS ANNE 2F', + Locations.SS_ANNE_3F: 'SS ANNE 3F', + Locations.SS_ANNE_B1F: 'SS ANNE B1F', + Locations.SS_ANNE_BOW: 'SS ANNE BOW', + Locations.SS_ANNE_KITCHEN: 'SS ANNE KITCHEN', + Locations.SS_ANNE_CAPTAINS_ROOM: 'SS ANNE CAPTAIN\'S ROOM', + Locations.SS_ANNE_1F_ROOMS: 'SS ANNE 1F ROOMS', + Locations.SS_ANNE_2F_ROOMS: 'SS ANNE 2F ROOMS', + Locations.SS_ANNE_B1F_ROOMS: 'SS ANNE B1F ROOMS', + Locations.UNUSED_MAP_69: 'UNUSED MAP 69', + Locations.UNUSED_MAP_6A: 'UNUSED MAP 6A', + Locations.UNUSED_MAP_6B: 'UNUSED MAP 6B', + Locations.VICTORY_ROAD_1F: 'VICTORY ROAD 1F', + Locations.UNUSED_MAP_6D: 'UNUSED MAP 6D', + Locations.UNUSED_MAP_6E: 'UNUSED MAP 6E', + Locations.UNUSED_MAP_6F: 'UNUSED MAP 6F', + Locations.UNUSED_MAP_70: 'UNUSED MAP 70', + Locations.LANCES_ROOM: 'LANCES ROOM', + Locations.UNUSED_MAP_72: 'UNUSED MAP 72', + Locations.UNUSED_MAP_73: 'UNUSED MAP 73', + Locations.UNUSED_MAP_74: 'UNUSED MAP 74', + Locations.UNUSED_MAP_75: 'UNUSED MAP 75', + Locations.HALL_OF_FAME: 'HALL OF FAME', + Locations.UNDERGROUND_PATH_NORTH_SOUTH: 'UNDERGROUND PATH NORTH SOUTH', + Locations.CHAMPIONS_ROOM: 'CHAMPION\'S ROOM', + Locations.UNDERGROUND_PATH_WEST_EAST: 'UNDERGROUND PATH WEST EAST', + Locations.CELADON_MART_1F: 'CELADON MART 1F', + Locations.CELADON_MART_2F: 'CELADON MART 2F', + Locations.CELADON_MART_3F: 'CELADON MART 3F', + Locations.CELADON_MART_4F: 'CELADON MART 4F', + Locations.CELADON_MART_ROOF: 'CELADON MART ROOF', + Locations.CELADON_MART_ELEVATOR: 'CELADON MART ELEVATOR', + Locations.CELADON_MANSION_1F: 'CELADON MANSION 1F', + Locations.CELADON_MANSION_2F: 'CELADON MANSION 2F', + Locations.CELADON_MANSION_3F: 'CELADON MANSION 3F', + Locations.CELADON_MANSION_ROOF: 'CELADON MANSION ROOF', + Locations.CELADON_MANSION_ROOF_HOUSE: 'CELADON MANSION ROOF HOUSE', + Locations.CELADON_POKECENTER: 'CELADON POKECENTER', + Locations.CELADON_GYM: 'CELADON GYM', + Locations.GAME_CORNER: 'GAME CORNER', + Locations.CELADON_MART_5F: 'CELADON MART 5F', + Locations.GAME_CORNER_PRIZE_ROOM: 'GAME CORNER PRIZE ROOM', + Locations.CELADON_DINER: 'CELADON DINER', + Locations.CELADON_CHIEF_HOUSE: 'CELADON CHIEF HOUSE', + Locations.CELADON_HOTEL: 'CELADON HOTEL', + Locations.LAVENDER_POKECENTER: 'LAVENDER POKECENTER', + Locations.POKEMON_TOWER_1F: 'POKEMON TOWER 1F', + Locations.POKEMON_TOWER_2F: 'POKEMON TOWER 2F', + Locations.POKEMON_TOWER_3F: 'POKEMON TOWER 3F', + Locations.POKEMON_TOWER_4F: 'POKEMON TOWER 4F', + Locations.POKEMON_TOWER_5F: 'POKEMON TOWER 5F', + Locations.POKEMON_TOWER_6F: 'POKEMON TOWER 6F', + Locations.POKEMON_TOWER_7F: 'POKEMON TOWER 7F', + Locations.MR_FUJIS_HOUSE: 'MR FUJIS HOUSE', + Locations.LAVENDER_MART: 'LAVENDER MART', + Locations.LAVENDER_CUBONE_HOUSE: 'LAVENDER CUBONE HOUSE', + Locations.FUCHSIA_MART: 'FUCHSIA MART', + Locations.FUCHSIA_BILLS_GRANDPAS_HOUSE: 'FUCHSIA BILL\'S GRANDPAS HOUSE', + Locations.FUCHSIA_POKECENTER: 'FUCHSIA POKECENTER', + Locations.WARDENS_HOUSE: 'WARDENS HOUSE', + Locations.SAFARI_ZONE_GATE: 'SAFARI ZONE GATE', + Locations.FUCHSIA_GYM: 'FUCHSIA GYM', + Locations.FUCHSIA_MEETING_ROOM: 'FUCHSIA MEETING ROOM', + Locations.SEAFOAM_ISLANDS_B1F: 'SEAFOAM ISLANDS B1F', + Locations.SEAFOAM_ISLANDS_B2F: 'SEAFOAM ISLANDS B2F', + Locations.SEAFOAM_ISLANDS_B3F: 'SEAFOAM ISLANDS B3F', + Locations.SEAFOAM_ISLANDS_B4F: 'SEAFOAM ISLANDS B4F', + Locations.VERMILION_OLD_ROD_HOUSE: 'VERMILION OLD ROD HOUSE', + Locations.FUCHSIA_GOOD_ROD_HOUSE: 'FUCHSIA GOOD ROD HOUSE', + Locations.POKEMON_MANSION_1F: 'POKEMON MANSION 1F', + Locations.CINNABAR_GYM: 'CINNABAR GYM', + Locations.CINNABAR_LAB: 'CINNABAR LAB', + Locations.CINNABAR_LAB_TRADE_ROOM: 'CINNABAR LAB TRADE ROOM', + Locations.CINNABAR_LAB_METRONOME_ROOM: 'CINNABAR LAB METRONOME ROOM', + Locations.CINNABAR_LAB_FOSSIL_ROOM: 'CINNABAR LAB FOSSIL ROOM', + Locations.CINNABAR_POKECENTER: 'CINNABAR POKECENTER', + Locations.CINNABAR_MART: 'CINNABAR MART', + Locations.CINNABAR_MART_COPY: 'CINNABAR MART COPY', + Locations.INDIGO_PLATEAU_LOBBY: 'INDIGO PLATEAU LOBBY', + Locations.COPYCATS_HOUSE_1F: 'COPYCATS HOUSE 1F', + Locations.COPYCATS_HOUSE_2F: 'COPYCATS HOUSE 2F', + Locations.FIGHTING_DOJO: 'FIGHTING DOJO', + Locations.SAFFRON_GYM: 'SAFFRON GYM', + Locations.SAFFRON_PIDGEY_HOUSE: 'SAFFRON PIDGEY HOUSE', + Locations.SAFFRON_MART: 'SAFFRON MART', + Locations.SILPH_CO_1F: 'SILPH CO 1F', + Locations.SAFFRON_POKECENTER: 'SAFFRON POKECENTER', + Locations.MR_PSYCHICS_HOUSE: 'MR PSYCHICS HOUSE', + Locations.ROUTE_15_GATE_1F: 'ROUTE 15 GATE 1F', + Locations.ROUTE_15_GATE_2F: 'ROUTE 15 GATE 2F', + Locations.ROUTE_16_GATE_1F: 'ROUTE 16 GATE 1F', + Locations.ROUTE_16_GATE_2F: 'ROUTE 16 GATE 2F', + Locations.ROUTE_16_FLY_HOUSE: 'ROUTE 16 FLY HOUSE', + Locations.ROUTE_12_SUPER_ROD_HOUSE: 'ROUTE 12 SUPER ROD HOUSE', + Locations.ROUTE_18_GATE_1F: 'ROUTE 18 GATE 1F', + Locations.ROUTE_18_GATE_2F: 'ROUTE 18 GATE 2F', + Locations.SEAFOAM_ISLANDS_1F: 'SEAFOAM ISLANDS 1F', + Locations.ROUTE_22_GATE: 'ROUTE 22 GATE', + Locations.VICTORY_ROAD_2F: 'VICTORY ROAD 2F', + Locations.ROUTE_12_GATE_2F: 'ROUTE 12 GATE 2F', + Locations.VERMILION_TRADE_HOUSE: 'VERMILION TRADE HOUSE', + Locations.DIGLETTS_CAVE: 'DIGLETTS CAVE', + Locations.VICTORY_ROAD_3F: 'VICTORY ROAD 3F', + Locations.ROCKET_HIDEOUT_B1F: 'ROCKET HIDEOUT B1F', + Locations.ROCKET_HIDEOUT_B2F: 'ROCKET HIDEOUT B2F', + Locations.ROCKET_HIDEOUT_B3F: 'ROCKET HIDEOUT B3F', + Locations.ROCKET_HIDEOUT_B4F: 'ROCKET HIDEOUT B4F', + Locations.ROCKET_HIDEOUT_ELEVATOR: 'ROCKET HIDEOUT ELEVATOR', + Locations.UNUSED_MAP_CC: 'UNUSED MAP CC', + Locations.UNUSED_MAP_CD: 'UNUSED MAP CD', + Locations.UNUSED_MAP_CE: 'UNUSED MAP CE', + Locations.SILPH_CO_2F: 'SILPH CO 2F', + Locations.SILPH_CO_3F: 'SILPH CO 3F', + Locations.SILPH_CO_4F: 'SILPH CO 4F', + Locations.SILPH_CO_5F: 'SILPH CO 5F', + Locations.SILPH_CO_6F: 'SILPH CO 6F', + Locations.SILPH_CO_7F: 'SILPH CO 7F', + Locations.SILPH_CO_8F: 'SILPH CO 8F', + Locations.POKEMON_MANSION_2F: 'POKEMON MANSION 2F', + Locations.POKEMON_MANSION_3F: 'POKEMON MANSION 3F', + Locations.POKEMON_MANSION_B1F: 'POKEMON MANSION B1F', + Locations.SAFARI_ZONE_EAST: 'SAFARI ZONE EAST', + Locations.SAFARI_ZONE_NORTH: 'SAFARI ZONE NORTH', + Locations.SAFARI_ZONE_WEST: 'SAFARI ZONE WEST', + Locations.SAFARI_ZONE_CENTER: 'SAFARI ZONE CENTER', + Locations.SAFARI_ZONE_CENTER_REST_HOUSE: 'SAFARI ZONE CENTER REST HOUSE', + Locations.SAFARI_ZONE_SECRET_HOUSE: 'SAFARI ZONE SECRET HOUSE', + Locations.SAFARI_ZONE_WEST_REST_HOUSE: 'SAFARI ZONE WEST REST HOUSE', + Locations.SAFARI_ZONE_EAST_REST_HOUSE: 'SAFARI ZONE EAST REST HOUSE', + Locations.SAFARI_ZONE_NORTH_REST_HOUSE: 'SAFARI ZONE NORTH REST HOUSE', + Locations.CERULEAN_CAVE_2F: 'CERULEAN CAVE 2F', + Locations.CERULEAN_CAVE_B1F: 'CERULEAN CAVE B1F', + Locations.CERULEAN_CAVE_1F: 'CERULEAN CAVE 1F', + Locations.NAME_RATERS_HOUSE: 'NAME RATER\'S HOUSE', + Locations.CERULEAN_BADGE_HOUSE: 'CERULEAN BADGE HOUSE', + Locations.UNUSED_MAP_E7: 'UNUSED MAP E7', + Locations.ROCK_TUNNEL_B1F: 'ROCK TUNNEL B1F', + Locations.SILPH_CO_9F: 'SILPH CO 9F', + Locations.SILPH_CO_10F: 'SILPH CO 10F', + Locations.SILPH_CO_11F: 'SILPH CO 11F', + Locations.SILPH_CO_ELEVATOR: 'SILPH CO ELEVATOR', + Locations.UNUSED_MAP_ED: 'UNUSED MAP ED', + Locations.UNUSED_MAP_EE: 'UNUSED MAP EE', + Locations.TRADE_CENTER: 'TRADE CENTER', + Locations.COLOSSEUM: 'COLOSSEUM', + Locations.UNUSED_MAP_F1: 'UNUSED MAP F1', + Locations.UNUSED_MAP_F2: 'UNUSED MAP F2', + Locations.UNUSED_MAP_F3: 'UNUSED MAP F3', + Locations.UNUSED_MAP_F4: 'UNUSED MAP F4', + Locations.LORELEIS_ROOM: 'LORELEI\'S ROOM', + Locations.BRUNOS_ROOM: 'BRUNO\'S ROOM', + Locations.AGATHAS_ROOM: 'AGATHA\'S ROOM', +} \ No newline at end of file From 6d7e4f7847f206b120fea0f07ca45f4727b48181 Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Mon, 6 Nov 2023 12:04:47 -0500 Subject: [PATCH 24/74] Remove location constants from constants.py after their move --- .../game_wrapper_pokemon_gen1/constants.py | 501 ------------------ 1 file changed, 501 deletions(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py b/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py index 770fcea22..af5e2f188 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py @@ -397,507 +397,6 @@ class Sprites(Enum): LYING_OLD_MAN_UNUSED_2 = 0x47 LYING_OLD_MAN = 0x48 -class Maps(Enum): - PALLET_TOWN = 0x00 - VIRIDIAN_CITY = 0x01 - PEWTER_CITY = 0x02 - CERULEAN_CITY = 0x03 - LAVENDER_TOWN = 0x04 - VERMILION_CITY = 0x05 - CELADON_CITY = 0x06 - FUCHSIA_CITY = 0x07 - CINNABAR_ISLAND = 0x08 - INDIGO_PLATEAU = 0x09 - SAFFRON_CITY = 0x0A - UNUSED_MAP_0B = 0x0B - ROUTE_1 = 0x0C - ROUTE_2 = 0x0D - ROUTE_3 = 0x0E - ROUTE_4 = 0x0F - ROUTE_5 = 0x10 - ROUTE_6 = 0x11 - ROUTE_7 = 0x12 - ROUTE_8 = 0x13 - ROUTE_9 = 0x14 - ROUTE_10 = 0x15 - ROUTE_11 = 0x16 - ROUTE_12 = 0x17 - ROUTE_13 = 0x18 - ROUTE_14 = 0x19 - ROUTE_15 = 0x1A - ROUTE_16 = 0x1B - ROUTE_17 = 0x1C - ROUTE_18 = 0x1D - ROUTE_19 = 0x1E - ROUTE_20 = 0x1F - ROUTE_21 = 0x20 - ROUTE_22 = 0x21 - ROUTE_23 = 0x22 - ROUTE_24 = 0x23 - ROUTE_25 = 0x24 - REDS_HOUSE_1F = 0x25 - REDS_HOUSE_2F = 0x26 - BLUES_HOUSE = 0x27 - OAKS_LAB = 0x28 - VIRIDIAN_POKECENTER = 0x29 - VIRIDIAN_MART = 0x2A - VIRIDIAN_SCHOOL_HOUSE = 0x2B - VIRIDIAN_NICKNAME_HOUSE = 0x2C - VIRIDIAN_GYM = 0x2D - DIGLETTS_CAVE_ROUTE_2 = 0x2E - VIRIDIAN_FOREST_NORTH_GATE = 0x2F - ROUTE_2_TRADE_HOUSE = 0x30 - ROUTE_2_GATE = 0x31 - VIRIDIAN_FOREST_SOUTH_GATE = 0x32 - VIRIDIAN_FOREST = 0x33 - MUSEUM_1F = 0x34 - MUSEUM_2F = 0x35 - PEWTER_GYM = 0x36 - PEWTER_NIDORAN_HOUSE = 0x37 - PEWTER_MART = 0x38 - PEWTER_SPEECH_HOUSE = 0x39 - PEWTER_POKECENTER = 0x3A - MT_MOON_1F = 0x3B - MT_MOON_B1F = 0x3C - MT_MOON_B2F = 0x3D - CERULEAN_TRASHED_HOUSE = 0x3E - CERULEAN_TRADE_HOUSE = 0x3F - CERULEAN_POKECENTER = 0x40 - CERULEAN_GYM = 0x41 - BIKE_SHOP = 0x42 - CERULEAN_MART = 0x43 - MT_MOON_POKECENTER = 0x44 - CERULEAN_TRASHED_HOUSE_COPY = 0x45 - ROUTE_5_GATE = 0x46 - UNDERGROUND_PATH_ROUTE_5 = 0x47 - DAYCARE = 0x48 - ROUTE_6_GATE = 0x49 - UNDERGROUND_PATH_ROUTE_6 = 0x4A - UNDERGROUND_PATH_ROUTE_6_COPY = 0x4B - ROUTE_7_GATE = 0x4C - UNDERGROUND_PATH_ROUTE_7 = 0x4D - UNDERGROUND_PATH_ROUTE_7_COPY = 0x4E - ROUTE_8_GATE = 0x4F - UNDERGROUND_PATH_ROUTE_8 = 0x50 - ROCK_TUNNEL_POKECENTER = 0x51 - ROCK_TUNNEL_1F = 0x52 - POWER_PLANT = 0x53 - ROUTE_11_GATE_1F = 0x54 - DIGLETTS_CAVE_ROUTE_11 = 0x55 - ROUTE_11_GATE_2F = 0x56 - ROUTE_12_GATE_1F = 0x57 - BILLS_HOUSE = 0x58 - VERMILION_POKECENTER = 0x59 - POKEMON_FAN_CLUB = 0x5A - VERMILION_MART = 0x5B - VERMILION_GYM = 0x5C - VERMILION_PIDGEY_HOUSE = 0x5D - VERMILION_DOCK = 0x5E - SS_ANNE_1F = 0x5F - SS_ANNE_2F = 0x60 - SS_ANNE_3F = 0x61 - SS_ANNE_B1F = 0x62 - SS_ANNE_BOW = 0x63 - SS_ANNE_KITCHEN = 0x64 - SS_ANNE_CAPTAINS_ROOM = 0x65 - SS_ANNE_1F_ROOMS = 0x66 - SS_ANNE_2F_ROOMS = 0x67 - SS_ANNE_B1F_ROOMS = 0x68 - UNUSED_MAP_69 = 0x69 - UNUSED_MAP_6A = 0x6A - UNUSED_MAP_6B = 0x6B - VICTORY_ROAD_1F = 0x6C - UNUSED_MAP_6D = 0x6D - UNUSED_MAP_6E = 0x6E - UNUSED_MAP_6F = 0x6F - UNUSED_MAP_70 = 0x70 - LANCES_ROOM = 0x71 - UNUSED_MAP_72 = 0x72 - UNUSED_MAP_73 = 0x73 - UNUSED_MAP_74 = 0x74 - UNUSED_MAP_75 = 0x75 - HALL_OF_FAME = 0x76 - UNDERGROUND_PATH_NORTH_SOUTH = 0x77 - CHAMPIONS_ROOM = 0x78 - UNDERGROUND_PATH_WEST_EAST = 0x79 - CELADON_MART_1F = 0x7A - CELADON_MART_2F = 0x7B - CELADON_MART_3F = 0x7C - CELADON_MART_4F = 0x7D - CELADON_MART_ROOF = 0x7E - CELADON_MART_ELEVATOR = 0x7F - CELADON_MANSION_1F = 0x80 - CELADON_MANSION_2F = 0x81 - CELADON_MANSION_3F = 0x82 - CELADON_MANSION_ROOF = 0x83 - CELADON_MANSION_ROOF_HOUSE = 0x84 - CELADON_POKECENTER = 0x85 - CELADON_GYM = 0x86 - GAME_CORNER = 0x87 - CELADON_MART_5F = 0x88 - GAME_CORNER_PRIZE_ROOM = 0x89 - CELADON_DINER = 0x8A - CELADON_CHIEF_HOUSE = 0x8B - CELADON_HOTEL = 0x8C - LAVENDER_POKECENTER = 0x8D - POKEMON_TOWER_1F = 0x8E - POKEMON_TOWER_2F = 0x8F - POKEMON_TOWER_3F = 0x90 - POKEMON_TOWER_4F = 0x91 - POKEMON_TOWER_5F = 0x92 - POKEMON_TOWER_6F = 0x93 - POKEMON_TOWER_7F = 0x94 - MR_FUJIS_HOUSE = 0x95 - LAVENDER_MART = 0x96 - LAVENDER_CUBONE_HOUSE = 0x97 - FUCHSIA_MART = 0x98 - FUCHSIA_BILLS_GRANDPAS_HOUSE = 0x99 - FUCHSIA_POKECENTER = 0x9A - WARDENS_HOUSE = 0x9B - SAFARI_ZONE_GATE = 0x9C - FUCHSIA_GYM = 0x9D - FUCHSIA_MEETING_ROOM = 0x9E - SEAFOAM_ISLANDS_B1F = 0x9F - SEAFOAM_ISLANDS_B2F = 0xA0 - SEAFOAM_ISLANDS_B3F = 0xA1 - SEAFOAM_ISLANDS_B4F = 0xA2 - VERMILION_OLD_ROD_HOUSE = 0xA3 - FUCHSIA_GOOD_ROD_HOUSE = 0xA4 - POKEMON_MANSION_1F = 0xA5 - CINNABAR_GYM = 0xA6 - CINNABAR_LAB = 0xA7 - CINNABAR_LAB_TRADE_ROOM = 0xA8 - CINNABAR_LAB_METRONOME_ROOM = 0xA9 - CINNABAR_LAB_FOSSIL_ROOM = 0xAA - CINNABAR_POKECENTER = 0xAB - CINNABAR_MART = 0xAC - CINNABAR_MART_COPY = 0xAD - INDIGO_PLATEAU_LOBBY = 0xAE - COPYCATS_HOUSE_1F = 0xAF - COPYCATS_HOUSE_2F = 0xB0 - FIGHTING_DOJO = 0xB1 - SAFFRON_GYM = 0xB2 - SAFFRON_PIDGEY_HOUSE = 0xB3 - SAFFRON_MART = 0xB4 - SILPH_CO_1F = 0xB5 - SAFFRON_POKECENTER = 0xB6 - MR_PSYCHICS_HOUSE = 0xB7 - ROUTE_15_GATE_1F = 0xB8 - ROUTE_15_GATE_2F = 0xB9 - ROUTE_16_GATE_1F = 0xBA - ROUTE_16_GATE_2F = 0xBB - ROUTE_16_FLY_HOUSE = 0xBC - ROUTE_12_SUPER_ROD_HOUSE = 0xBD - ROUTE_18_GATE_1F = 0xBE - ROUTE_18_GATE_2F = 0xBF - SEAFOAM_ISLANDS_1F = 0xC0 - ROUTE_22_GATE = 0xC1 - VICTORY_ROAD_2F = 0xC2 - ROUTE_12_GATE_2F = 0xC3 - VERMILION_TRADE_HOUSE = 0xC4 - DIGLETTS_CAVE = 0xC5 - VICTORY_ROAD_3F = 0xC6 - ROCKET_HIDEOUT_B1F = 0xC7 - ROCKET_HIDEOUT_B2F = 0xC8 - ROCKET_HIDEOUT_B3F = 0xC9 - ROCKET_HIDEOUT_B4F = 0xCA - ROCKET_HIDEOUT_ELEVATOR = 0xCB - UNUSED_MAP_CC = 0xCC - UNUSED_MAP_CD = 0xCD - UNUSED_MAP_CE = 0xCE - SILPH_CO_2F = 0xCF - SILPH_CO_3F = 0xD0 - SILPH_CO_4F = 0xD1 - SILPH_CO_5F = 0xD2 - SILPH_CO_6F = 0xD3 - SILPH_CO_7F = 0xD4 - SILPH_CO_8F = 0xD5 - POKEMON_MANSION_2F = 0xD6 - POKEMON_MANSION_3F = 0xD7 - POKEMON_MANSION_B1F = 0xD8 - SAFARI_ZONE_EAST = 0xD9 - SAFARI_ZONE_NORTH = 0xDA - SAFARI_ZONE_WEST = 0xDB - SAFARI_ZONE_CENTER = 0xDC - SAFARI_ZONE_CENTER_REST_HOUSE = 0xDD - SAFARI_ZONE_SECRET_HOUSE = 0xDE - SAFARI_ZONE_WEST_REST_HOUSE = 0xDF - SAFARI_ZONE_EAST_REST_HOUSE = 0xE0 - SAFARI_ZONE_NORTH_REST_HOUSE = 0xE1 - CERULEAN_CAVE_2F = 0xE2 - CERULEAN_CAVE_B1F = 0xE3 - CERULEAN_CAVE_1F = 0xE4 - NAME_RATERS_HOUSE = 0xE5 - CERULEAN_BADGE_HOUSE = 0xE6 - UNUSED_MAP_E7 = 0xE7 - ROCK_TUNNEL_B1F = 0xE8 - SILPH_CO_9F = 0xE9 - SILPH_CO_10F = 0xEA - SILPH_CO_11F = 0xEB - SILPH_CO_ELEVATOR = 0xEC - UNUSED_MAP_ED = 0xED - UNUSED_MAP_EE = 0xEE - TRADE_CENTER = 0xEF - COLOSSEUM = 0xF0 - UNUSED_MAP_F1 = 0xF1 - UNUSED_MAP_F2 = 0xF2 - UNUSED_MAP_F3 = 0xF3 - UNUSED_MAP_F4 = 0xF4 - LORELEIS_ROOM = 0xF5 - BRUNOS_ROOM = 0xF6 - AGATHAS_ROOM = 0xF7 - -MAP_NAMES = [ -'PALLET TOWN', -'VIRIDIAN CITY', -'PEWTER CITY', -'CERULEAN CITY', -'LAVENDER TOWN', -'VERMILION CITY', -'CELADON CITY', -'FUCHSIA CITY', -'CINNABAR ISLAND', -'INDIGO PLATEAU', -'SAFFRON CITY', -'UNUSED MAP 0B', -'ROUTE 1', -'ROUTE 2', -'ROUTE 3', -'ROUTE 4', -'ROUTE 5', -'ROUTE 6', -'ROUTE 7', -'ROUTE 8', -'ROUTE 9', -'ROUTE 10', -'ROUTE 11', -'ROUTE 12', -'ROUTE 13', -'ROUTE 14', -'ROUTE 15', -'ROUTE 16', -'ROUTE 17', -'ROUTE 18', -'ROUTE 19', -'ROUTE 20', -'ROUTE 21', -'ROUTE 22', -'ROUTE 23', -'ROUTE 24', -'ROUTE 25', -'RED\'S HOUSE 1F', -'RED\'S HOUSE 2F', -'BLUE\'S HOUSE', -'OAK\'S LAB', -'VIRIDIAN POKECENTER', -'VIRIDIAN MART', -'VIRIDIAN SCHOOL HOUSE', -'VIRIDIAN NICKNAME HOUSE', -'VIRIDIAN GYM', -'DIGLETTS CAVE ROUTE 2', -'VIRIDIAN FOREST NORTH GATE', -'ROUTE 2 TRADE HOUSE', -'ROUTE 2 GATE', -'VIRIDIAN FOREST SOUTH GATE', -'VIRIDIAN FOREST', -'MUSEUM 1F', -'MUSEUM 2F', -'PEWTER GYM', -'PEWTER NIDORAN HOUSE', -'PEWTER MART', -'PEWTER SPEECH HOUSE', -'PEWTER POKECENTER', -'MT MOON 1F', -'MT MOON B1F', -'MT MOON B2F', -'CERULEAN TRASHED HOUSE', -'CERULEAN TRADE HOUSE', -'CERULEAN POKECENTER', -'CERULEAN GYM', -'BIKE SHOP', -'CERULEAN MART', -'MT MOON POKECENTER', -'CERULEAN TRASHED HOUSE COPY', -'ROUTE 5 GATE', -'UNDERGROUND PATH ROUTE 5', -'DAYCARE', -'ROUTE 6 GATE', -'UNDERGROUND PATH ROUTE 6', -'UNDERGROUND PATH ROUTE 6 COPY', -'ROUTE 7 GATE', -'UNDERGROUND PATH ROUTE 7', -'UNDERGROUND PATH ROUTE 7 COPY', -'ROUTE 8 GATE', -'UNDERGROUND PATH ROUTE 8', -'ROCK TUNNEL POKECENTER', -'ROCK TUNNEL 1F', -'POWER PLANT', -'ROUTE 11 GATE 1F', -'DIGLETT\'S CAVE ROUTE 11', -'ROUTE 11 GATE 2F', -'ROUTE 12 GATE 1F', -'BILLS HOUSE', -'VERMILION POKECENTER', -'POKEMON FAN CLUB', -'VERMILION MART', -'VERMILION GYM', -'VERMILION PIDGEY HOUSE', -'VERMILION DOCK', -'SS ANNE 1F', -'SS ANNE 2F', -'SS ANNE 3F', -'SS ANNE B1F', -'SS ANNE BOW', -'SS ANNE KITCHEN', -'SS ANNE CAPTAIN\'S ROOM', -'SS ANNE 1F ROOMS', -'SS ANNE 2F ROOMS', -'SS ANNE B1F ROOMS', -'UNUSED MAP 69', -'UNUSED MAP 6A', -'UNUSED MAP 6B', -'VICTORY ROAD 1F', -'UNUSED MAP 6D', -'UNUSED MAP 6E', -'UNUSED MAP 6F', -'UNUSED MAP 70', -'LANCES ROOM', -'UNUSED MAP 72', -'UNUSED MAP 73', -'UNUSED MAP 74', -'UNUSED MAP 75', -'HALL OF FAME', -'UNDERGROUND PATH NORTH SOUTH', -'CHAMPION\'S ROOM', -'UNDERGROUND PATH WEST EAST', -'CELADON MART 1F', -'CELADON MART 2F', -'CELADON MART 3F', -'CELADON MART 4F', -'CELADON MART ROOF', -'CELADON MART ELEVATOR', -'CELADON MANSION 1F', -'CELADON MANSION 2F', -'CELADON MANSION 3F', -'CELADON MANSION ROOF', -'CELADON MANSION ROOF HOUSE', -'CELADON POKECENTER', -'CELADON GYM', -'GAME CORNER', -'CELADON MART 5F', -'GAME CORNER PRIZE ROOM', -'CELADON DINER', -'CELADON CHIEF HOUSE', -'CELADON HOTEL', -'LAVENDER POKECENTER', -'POKEMON TOWER 1F', -'POKEMON TOWER 2F', -'POKEMON TOWER 3F', -'POKEMON TOWER 4F', -'POKEMON TOWER 5F', -'POKEMON TOWER 6F', -'POKEMON TOWER 7F', -'MR FUJIS HOUSE', -'LAVENDER MART', -'LAVENDER CUBONE HOUSE', -'FUCHSIA MART', -'FUCHSIA BILL\'S GRANDPAS HOUSE', -'FUCHSIA POKECENTER', -'WARDENS HOUSE', -'SAFARI ZONE GATE', -'FUCHSIA GYM', -'FUCHSIA MEETING ROOM', -'SEAFOAM ISLANDS B1F', -'SEAFOAM ISLANDS B2F', -'SEAFOAM ISLANDS B3F', -'SEAFOAM ISLANDS B4F', -'VERMILION OLD ROD HOUSE', -'FUCHSIA GOOD ROD HOUSE', -'POKEMON MANSION 1F', -'CINNABAR GYM', -'CINNABAR LAB', -'CINNABAR LAB TRADE ROOM', -'CINNABAR LAB METRONOME ROOM', -'CINNABAR LAB FOSSIL ROOM', -'CINNABAR POKECENTER', -'CINNABAR MART', -'CINNABAR MART COPY', -'INDIGO PLATEAU LOBBY', -'COPYCATS HOUSE 1F', -'COPYCATS HOUSE 2F', -'FIGHTING DOJO', -'SAFFRON GYM', -'SAFFRON PIDGEY HOUSE', -'SAFFRON MART', -'SILPH CO 1F', -'SAFFRON POKECENTER', -'MR PSYCHICS HOUSE', -'ROUTE 15 GATE 1F', -'ROUTE 15 GATE 2F', -'ROUTE 16 GATE 1F', -'ROUTE 16 GATE 2F', -'ROUTE 16 FLY HOUSE', -'ROUTE 12 SUPER ROD HOUSE', -'ROUTE 18 GATE 1F', -'ROUTE 18 GATE 2F', -'SEAFOAM ISLANDS 1F', -'ROUTE 22 GATE', -'VICTORY ROAD 2F', -'ROUTE 12 GATE 2F', -'VERMILION TRADE HOUSE', -'DIGLETTS CAVE', -'VICTORY ROAD 3F', -'ROCKET HIDEOUT B1F', -'ROCKET HIDEOUT B2F', -'ROCKET HIDEOUT B3F', -'ROCKET HIDEOUT B4F', -'ROCKET HIDEOUT ELEVATOR', -'UNUSED MAP CC', -'UNUSED MAP CD', -'UNUSED MAP CE', -'SILPH CO 2F', -'SILPH CO 3F', -'SILPH CO 4F', -'SILPH CO 5F', -'SILPH CO 6F', -'SILPH CO 7F', -'SILPH CO 8F', -'POKEMON MANSION 2F', -'POKEMON MANSION 3F', -'POKEMON MANSION B1F', -'SAFARI ZONE EAST', -'SAFARI ZONE NORTH', -'SAFARI ZONE WEST', -'SAFARI ZONE CENTER', -'SAFARI ZONE CENTER REST HOUSE', -'SAFARI ZONE SECRET HOUSE', -'SAFARI ZONE WEST REST HOUSE', -'SAFARI ZONE EAST REST HOUSE', -'SAFARI ZONE NORTH REST HOUSE', -'CERULEAN CAVE 2F', -'CERULEAN CAVE B1F', -'CERULEAN CAVE 1F', -'NAME RATER\'S HOUSE', -'CERULEAN BADGE HOUSE', -'UNUSED MAP E7', -'ROCK TUNNEL B1F', -'SILPH CO 9F', -'SILPH CO 10F', -'SILPH CO 11F', -'SILPH CO ELEVATOR', -'UNUSED MAP ED', -'UNUSED MAP EE', -'TRADE CENTER', -'COLOSSEUM', -'UNUSED MAP F1', -'UNUSED MAP F2', -'UNUSED MAP F3', -'UNUSED MAP F4', -'LORELEI\'S ROOM', -'BRUNO\'S ROOM', -'AGATHA\'S ROOM', -] - class Statuses(Enum): ASLEEP = 4 POISONED = 8 From 5eb582f4bf202d568a597f5a81849e57054cd802 Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Mon, 6 Nov 2023 12:10:06 -0500 Subject: [PATCH 25/74] Change Pokemon enum to PokemonIds to avoid any confusion with Pokemon class --- .../plugins/game_wrapper_pokemon_gen1/data/pokemon/constants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/pokemon/constants.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/pokemon/constants.py index c3d46ae5e..dc3d0d042 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/data/pokemon/constants.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/pokemon/constants.py @@ -1,6 +1,6 @@ from enum import Enum -class Pokemon(Enum): +class PokemonIds(Enum): RHYDON = 0x01 KANGASKHAN = 0x02 NIDORAN_M = 0x03 From 2f23ad9e70fcbfd95db9082ad4cbbaee71ced440 Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Mon, 6 Nov 2023 13:22:03 -0500 Subject: [PATCH 26/74] Fix mapping dicts to use newly named PokemonIds --- .../data/pokemon/constants.py | 604 +++++++++--------- 1 file changed, 302 insertions(+), 302 deletions(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/pokemon/constants.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/pokemon/constants.py index dc3d0d042..76397dabe 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/data/pokemon/constants.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/pokemon/constants.py @@ -193,309 +193,309 @@ class PokemonIds(Enum): VICTREEBEL = 0xBE _POKEMON_POKEDEX_INDEX = { - Pokemon.BULBASAUR: 1, - Pokemon.IVYSAUR: 2, - Pokemon.VENUSAUR: 3, - Pokemon.CHARMANDER: 4, - Pokemon.CHARMELEON: 5, - Pokemon.CHARIZARD: 6, - Pokemon.SQUIRTLE: 7, - Pokemon.WARTORTLE: 8, - Pokemon.BLASTOISE: 9, - Pokemon.CATERPIE: 10, - Pokemon.METAPOD: 11, - Pokemon.BUTTERFREE: 12, - Pokemon.WEEDLE: 13, - Pokemon.KAKUNA: 14, - Pokemon.BEEDRILL: 15, - Pokemon.PIDGEY: 16, - Pokemon.PIDGEOTTO: 17, - Pokemon.PIDGEOT: 18, - Pokemon.RATTATA: 19, - Pokemon.RATICATE: 20, - Pokemon.SPEAROW: 21, - Pokemon.FEAROW: 22, - Pokemon.EKANS: 23, - Pokemon.ARBOK: 24, - Pokemon.PIKACHU: 25, - Pokemon.RAICHU: 26, - Pokemon.SANDSHREW: 27, - Pokemon.SANDSLASH: 28, - Pokemon.NIDORAN_F: 29, - Pokemon.NIDORINA: 30, - Pokemon.NIDOQUEEN: 31, - Pokemon.NIDORAN_M: 32, - Pokemon.NIDORINO: 33, - Pokemon.NIDOKING: 34, - Pokemon.CLEFAIRY: 35, - Pokemon.CLEFABLE: 36, - Pokemon.VULPIX: 37, - Pokemon.NINETALES: 38, - Pokemon.JIGGLYPUFF: 39, - Pokemon.WIGGLYTUFF: 40, - Pokemon.ZUBAT: 41, - Pokemon.GOLBAT: 42, - Pokemon.ODDISH: 43, - Pokemon.GLOOM: 44, - Pokemon.VILEPLUME: 45, - Pokemon.PARAS: 46, - Pokemon.PARASECT: 47, - Pokemon.VENONAT: 48, - Pokemon.VENOMOTH: 49, - Pokemon.DIGLETT: 50, - Pokemon.DUGTRIO: 51, - Pokemon.MEOWTH: 52, - Pokemon.PERSIAN: 53, - Pokemon.PSYDUCK: 54, - Pokemon.GOLDUCK: 55, - Pokemon.MANKEY: 56, - Pokemon.PRIMEAPE: 57, - Pokemon.GROWLITHE: 58, - Pokemon.ARCANINE: 59, - Pokemon.POLIWAG: 60, - Pokemon.POLIWHIRL: 61, - Pokemon.POLIWRATH: 62, - Pokemon.ABRA: 63, - Pokemon.KADABRA: 64, - Pokemon.ALAKAZAM: 65, - Pokemon.MACHOP: 66, - Pokemon.MACHOKE: 67, - Pokemon.MACHAMP: 68, - Pokemon.BELLSPROUT: 69, - Pokemon.WEEPINBELL: 70, - Pokemon.VICTREEBEL: 71, - Pokemon.TENTACOOL: 72, - Pokemon.TENTACRUEL: 73, - Pokemon.GEODUDE: 74, - Pokemon.GRAVELER: 75, - Pokemon.GOLEM: 76, - Pokemon.PONYTA: 77, - Pokemon.RAPIDASH: 78, - Pokemon.SLOWPOKE: 79, - Pokemon.SLOWBRO: 80, - Pokemon.MAGNEMITE: 81, - Pokemon.MAGNETON: 82, - Pokemon.FARFETCHD: 83, - Pokemon.DODUO: 84, - Pokemon.DODRIO: 85, - Pokemon.SEEL: 86, - Pokemon.DEWGONG: 87, - Pokemon.GRIMER: 88, - Pokemon.MUK: 89, - Pokemon.SHELLDER: 90, - Pokemon.CLOYSTER: 91, - Pokemon.GASTLY: 92, - Pokemon.HAUNTER: 93, - Pokemon.GENGAR: 94, - Pokemon.ONIX: 95, - Pokemon.DROWZEE: 96, - Pokemon.HYPNO: 97, - Pokemon.KRABBY: 98, - Pokemon.KINGLER: 99, - Pokemon.VOLTORB: 100, - Pokemon.ELECTRODE: 101, - Pokemon.EXEGGCUTE: 102, - Pokemon.EXEGGUTOR: 103, - Pokemon.CUBONE: 104, - Pokemon.MAROWAK: 105, - Pokemon.HITMONLEE: 106, - Pokemon.HITMONCHAN: 107, - Pokemon.LICKITUNG: 108, - Pokemon.KOFFING: 109, - Pokemon.WEEZING: 110, - Pokemon.RHYHORN: 111, - Pokemon.RHYDON: 112, - Pokemon.CHANSEY: 113, - Pokemon.TANGELA: 114, - Pokemon.KANGASKHAN: 115, - Pokemon.HORSEA: 116, - Pokemon.SEADRA: 117, - Pokemon.GOLDEEN: 118, - Pokemon.SEAKING: 119, - Pokemon.STARYU: 120, - Pokemon.STARMIE: 121, - Pokemon.MR_MIME: 122, - Pokemon.SCYTHER: 123, - Pokemon.JYNX: 124, - Pokemon.ELECTABUZZ: 125, - Pokemon.MAGMAR: 126, - Pokemon.PINSIR: 127, - Pokemon.TAUROS: 128, - Pokemon.MAGIKARP: 129, - Pokemon.GYARADOS: 130, - Pokemon.LAPRAS: 131, - Pokemon.DITTO: 132, - Pokemon.EEVEE: 133, - Pokemon.VAPOREON: 134, - Pokemon.JOLTEON: 135, - Pokemon.FLAREON: 136, - Pokemon.PORYGON: 137, - Pokemon.OMANYTE: 138, - Pokemon.OMASTAR: 139, - Pokemon.KABUTO: 140, - Pokemon.KABUTOPS: 141, - Pokemon.AERODACTYL: 142, - Pokemon.SNORLAX: 143, - Pokemon.ARTICUNO: 144, - Pokemon.ZAPDOS: 145, - Pokemon.MOLTRES: 146, - Pokemon.DRATINI: 147, - Pokemon.DRAGONAIR: 148, - Pokemon.DRAGONITE: 149, - Pokemon.MEWTWO: 150, - Pokemon.MEW: 151 + PokemonIds.BULBASAUR: 1, + PokemonIds.IVYSAUR: 2, + PokemonIds.VENUSAUR: 3, + PokemonIds.CHARMANDER: 4, + PokemonIds.CHARMELEON: 5, + PokemonIds.CHARIZARD: 6, + PokemonIds.SQUIRTLE: 7, + PokemonIds.WARTORTLE: 8, + PokemonIds.BLASTOISE: 9, + PokemonIds.CATERPIE: 10, + PokemonIds.METAPOD: 11, + PokemonIds.BUTTERFREE: 12, + PokemonIds.WEEDLE: 13, + PokemonIds.KAKUNA: 14, + PokemonIds.BEEDRILL: 15, + PokemonIds.PIDGEY: 16, + PokemonIds.PIDGEOTTO: 17, + PokemonIds.PIDGEOT: 18, + PokemonIds.RATTATA: 19, + PokemonIds.RATICATE: 20, + PokemonIds.SPEAROW: 21, + PokemonIds.FEAROW: 22, + PokemonIds.EKANS: 23, + PokemonIds.ARBOK: 24, + PokemonIds.PIKACHU: 25, + PokemonIds.RAICHU: 26, + PokemonIds.SANDSHREW: 27, + PokemonIds.SANDSLASH: 28, + PokemonIds.NIDORAN_F: 29, + PokemonIds.NIDORINA: 30, + PokemonIds.NIDOQUEEN: 31, + PokemonIds.NIDORAN_M: 32, + PokemonIds.NIDORINO: 33, + PokemonIds.NIDOKING: 34, + PokemonIds.CLEFAIRY: 35, + PokemonIds.CLEFABLE: 36, + PokemonIds.VULPIX: 37, + PokemonIds.NINETALES: 38, + PokemonIds.JIGGLYPUFF: 39, + PokemonIds.WIGGLYTUFF: 40, + PokemonIds.ZUBAT: 41, + PokemonIds.GOLBAT: 42, + PokemonIds.ODDISH: 43, + PokemonIds.GLOOM: 44, + PokemonIds.VILEPLUME: 45, + PokemonIds.PARAS: 46, + PokemonIds.PARASECT: 47, + PokemonIds.VENONAT: 48, + PokemonIds.VENOMOTH: 49, + PokemonIds.DIGLETT: 50, + PokemonIds.DUGTRIO: 51, + PokemonIds.MEOWTH: 52, + PokemonIds.PERSIAN: 53, + PokemonIds.PSYDUCK: 54, + PokemonIds.GOLDUCK: 55, + PokemonIds.MANKEY: 56, + PokemonIds.PRIMEAPE: 57, + PokemonIds.GROWLITHE: 58, + PokemonIds.ARCANINE: 59, + PokemonIds.POLIWAG: 60, + PokemonIds.POLIWHIRL: 61, + PokemonIds.POLIWRATH: 62, + PokemonIds.ABRA: 63, + PokemonIds.KADABRA: 64, + PokemonIds.ALAKAZAM: 65, + PokemonIds.MACHOP: 66, + PokemonIds.MACHOKE: 67, + PokemonIds.MACHAMP: 68, + PokemonIds.BELLSPROUT: 69, + PokemonIds.WEEPINBELL: 70, + PokemonIds.VICTREEBEL: 71, + PokemonIds.TENTACOOL: 72, + PokemonIds.TENTACRUEL: 73, + PokemonIds.GEODUDE: 74, + PokemonIds.GRAVELER: 75, + PokemonIds.GOLEM: 76, + PokemonIds.PONYTA: 77, + PokemonIds.RAPIDASH: 78, + PokemonIds.SLOWPOKE: 79, + PokemonIds.SLOWBRO: 80, + PokemonIds.MAGNEMITE: 81, + PokemonIds.MAGNETON: 82, + PokemonIds.FARFETCHD: 83, + PokemonIds.DODUO: 84, + PokemonIds.DODRIO: 85, + PokemonIds.SEEL: 86, + PokemonIds.DEWGONG: 87, + PokemonIds.GRIMER: 88, + PokemonIds.MUK: 89, + PokemonIds.SHELLDER: 90, + PokemonIds.CLOYSTER: 91, + PokemonIds.GASTLY: 92, + PokemonIds.HAUNTER: 93, + PokemonIds.GENGAR: 94, + PokemonIds.ONIX: 95, + PokemonIds.DROWZEE: 96, + PokemonIds.HYPNO: 97, + PokemonIds.KRABBY: 98, + PokemonIds.KINGLER: 99, + PokemonIds.VOLTORB: 100, + PokemonIds.ELECTRODE: 101, + PokemonIds.EXEGGCUTE: 102, + PokemonIds.EXEGGUTOR: 103, + PokemonIds.CUBONE: 104, + PokemonIds.MAROWAK: 105, + PokemonIds.HITMONLEE: 106, + PokemonIds.HITMONCHAN: 107, + PokemonIds.LICKITUNG: 108, + PokemonIds.KOFFING: 109, + PokemonIds.WEEZING: 110, + PokemonIds.RHYHORN: 111, + PokemonIds.RHYDON: 112, + PokemonIds.CHANSEY: 113, + PokemonIds.TANGELA: 114, + PokemonIds.KANGASKHAN: 115, + PokemonIds.HORSEA: 116, + PokemonIds.SEADRA: 117, + PokemonIds.GOLDEEN: 118, + PokemonIds.SEAKING: 119, + PokemonIds.STARYU: 120, + PokemonIds.STARMIE: 121, + PokemonIds.MR_MIME: 122, + PokemonIds.SCYTHER: 123, + PokemonIds.JYNX: 124, + PokemonIds.ELECTABUZZ: 125, + PokemonIds.MAGMAR: 126, + PokemonIds.PINSIR: 127, + PokemonIds.TAUROS: 128, + PokemonIds.MAGIKARP: 129, + PokemonIds.GYARADOS: 130, + PokemonIds.LAPRAS: 131, + PokemonIds.DITTO: 132, + PokemonIds.EEVEE: 133, + PokemonIds.VAPOREON: 134, + PokemonIds.JOLTEON: 135, + PokemonIds.FLAREON: 136, + PokemonIds.PORYGON: 137, + PokemonIds.OMANYTE: 138, + PokemonIds.OMASTAR: 139, + PokemonIds.KABUTO: 140, + PokemonIds.KABUTOPS: 141, + PokemonIds.AERODACTYL: 142, + PokemonIds.SNORLAX: 143, + PokemonIds.ARTICUNO: 144, + PokemonIds.ZAPDOS: 145, + PokemonIds.MOLTRES: 146, + PokemonIds.DRATINI: 147, + PokemonIds.DRAGONAIR: 148, + PokemonIds.DRAGONITE: 149, + PokemonIds.MEWTWO: 150, + PokemonIds.MEW: 151 } _POKEMON_NAMES = { - Pokemon.BULBASAUR: "Bulbasaur", - Pokemon.IVYSAUR: "Ivysaur", - Pokemon.VENUSAUR: "Venusaur", - Pokemon.CHARMANDER: "Charmander", - Pokemon.CHARMELEON: "Charmeleon", - Pokemon.CHARIZARD: "Charizard", - Pokemon.SQUIRTLE: "Squirtle", - Pokemon.WARTORTLE: "Wartortle", - Pokemon.BLASTOISE: "Blastoise", - Pokemon.CATERPIE: "Caterpie", - Pokemon.METAPOD: "Metapod", - Pokemon.BUTTERFREE: "Butterfree", - Pokemon.CATERPIE: "Weedle", - Pokemon.KAKUNA: "Kakuna", - Pokemon.BEEDRILL: "Beedrill", - Pokemon.PIDGEY: "Pidgey", - Pokemon.PIDGEOTTO: "Pidgeotto", - Pokemon.PIDGEOT: "Pidgeot", - Pokemon.RATTATA: "Rattata", - Pokemon.RATICATE: "Raticate", - Pokemon.SPEAROW: "Spearow", - Pokemon.FEAROW: "Fearow", - Pokemon.EKANS: "Ekans", - Pokemon.ARBOK: "Arbok", - Pokemon.PIKACHU: "Pikachu", - Pokemon.RAICHU: "Raichu", - Pokemon.SANDSHREW: "Sandshrew", - Pokemon.SANDSLASH: "Sandslash", - Pokemon.NIDORAN_F: "Nidoran♀", - Pokemon.NIDORINA: "Nidorina", - Pokemon.NIDOQUEEN: "Nidoqueen", - Pokemon.NIDORAN_M: "Nidoran♂", - Pokemon.NIDORINO: "Nidorino", - Pokemon.NIDOKING: "Nidoking", - Pokemon.CLEFAIRY: "Clefairy", - Pokemon.CLEFABLE: "Clefable", - Pokemon.VULPIX: "Vulpix", - Pokemon.NINETALES: "Ninetales", - Pokemon.JIGGLYPUFF: "Jigglypuff", - Pokemon.WIGGLYTUFF: "Wigglytuff", - Pokemon.ZUBAT: "Zubat", - Pokemon.GOLBAT: "Golbat", - Pokemon.ODDISH: "Oddish", - Pokemon.GLOOM: "Gloom", - Pokemon.VILEPLUME: "Vileplume", - Pokemon.PARAS: "Paras", - Pokemon.PARASECT: "Parasect", - Pokemon.VENONAT: "Venonat", - Pokemon.VENOMOTH: "Venomoth", - Pokemon.DIGLETT: "Diglett", - Pokemon.DUGTRIO: "Dugtrio", - Pokemon.MEOWTH: "Meowth", - Pokemon.PERSIAN: "Persian", - Pokemon.PSYDUCK: "Psyduck", - Pokemon.GOLDUCK: "Golduck", - Pokemon.MANKEY: "Mankey", - Pokemon.PRIMEAPE: "Primeape", - Pokemon.GROWLITHE: "Growlithe", - Pokemon.ARCANINE: "Arcanine", - Pokemon.POLIWAG: "Poliwag", - Pokemon.POLIWHIRL: "Poliwhirl", - Pokemon.POLIWRATH: "Poliwrath", - Pokemon.ABRA: "Abra", - Pokemon.KADABRA: "Kadabra", - Pokemon.ALAKAZAM: "Alakazam", - Pokemon.MACHOP: "Machop", - Pokemon.MACHOKE: "Machoke", - Pokemon.MACHAMP: "Machamp", - Pokemon.BELLSPROUT: "Bellsprout", - Pokemon.WEEPINBELL: "Weepinbell", - Pokemon.VICTREEBEL: "Victreebel", - Pokemon.TENTACOOL: "Tentacool", - Pokemon.TENTACRUEL: "Tentacruel", - Pokemon.GEODUDE: "Geodude", - Pokemon.GRAVELER: "Graveler", - Pokemon.GOLEM: "Golem", - Pokemon.PONYTA: "Ponyta", - Pokemon.RAPIDASH: "Rapidash", - Pokemon.SLOWPOKE: "Slowpoke", - Pokemon.SLOWBRO: "Slowbro", - Pokemon.MAGNEMITE: "Magnemite", - Pokemon.MAGNETON: "Magneton", - Pokemon.FARFETCHD: "Farfetch’d", - Pokemon.DODUO: "Doduo", - Pokemon.DODRIO: "Dodrio", - Pokemon.SEEL: "Seel", - Pokemon.DEWGONG: "Dewgong", - Pokemon.GRIMER: "Grimer", - Pokemon.MUK: "Muk", - Pokemon.SHELLDER: "Shellder", - Pokemon.CLOYSTER: "Cloyster", - Pokemon.GASTLY: "Gastly", - Pokemon.HAUNTER: "Haunter", - Pokemon.GENGAR: "Gengar", - Pokemon.ONIX: "Onix", - Pokemon.DROWZEE: "Drowzee", - Pokemon.HYPNO: "Hypno", - Pokemon.KRABBY: "Krabby", - Pokemon.KINGLER: "Kingler", - Pokemon.VOLTORB: "Voltorb", - Pokemon.ELECTRODE: "Electrode", - Pokemon.EXEGGCUTE: "Exeggcute", - Pokemon.EXEGGUTOR: "Exeggutor", - Pokemon.CUBONE: "Cubone", - Pokemon.MAROWAK: "Marowak", - Pokemon.HITMONLEE: "Hitmonlee", - Pokemon.HITMONCHAN: "Hitmonchan", - Pokemon.LICKITUNG: "Lickitung", - Pokemon.KOFFING: "Koffing", - Pokemon.WEEZING: "Weezing", - Pokemon.RHYHORN: "Rhyhorn", - Pokemon.RHYDON: "Rhydon", - Pokemon.CHANSEY: "Chansey", - Pokemon.TANGELA: "Tangela", - Pokemon.KANGASKHAN: "Kangaskhan", - Pokemon.HORSEA: "Horsea", - Pokemon.SEADRA: "Seadra", - Pokemon.GOLDEEN: "Goldeen", - Pokemon.SEAKING: "Seaking", - Pokemon.STARYU: "Staryu", - Pokemon.STARMIE: "Starmie", - Pokemon.MR_MIME: "Mr. Mime", - Pokemon.SCYTHER: "Scyther", - Pokemon.JYNX: "Jynx", - Pokemon.ELECTABUZZ: "Electabuzz", - Pokemon.MAGMAR: "Magmar", - Pokemon.PINSIR: "Pinsir", - Pokemon.TAUROS: "Tauros", - Pokemon.MAGIKARP: "Magikarp", - Pokemon.GYARADOS: "Gyarados", - Pokemon.LAPRAS: "Lapras", - Pokemon.DITTO: "Ditto", - Pokemon.EEVEE: "Eevee", - Pokemon.VAPOREON: "Vaporeon", - Pokemon.JOLTEON: "Jolteon", - Pokemon.FLAREON: "Flareon", - Pokemon.PORYGON: "Porygon", - Pokemon.OMANYTE: "Omanyte", - Pokemon.OMASTAR: "Omastar", - Pokemon.KABUTO: "Kabuto", - Pokemon.KABUTOPS: "Kabutops", - Pokemon.AERODACTYL: "Aerodactyl", - Pokemon.SNORLAX: "Snorlax", - Pokemon.ARTICUNO: "Articuno", - Pokemon.ZAPDOS: "Zapdos", - Pokemon.MOLTRES: "Moltres", - Pokemon.DRATINI: "Dratini", - Pokemon.DRAGONAIR: "Dragonair", - Pokemon.DRAGONITE: "Dragonite", - Pokemon.MEWTWO: "Mewtwo", - Pokemon.MEW: "Mew", + PokemonIds.BULBASAUR: "Bulbasaur", + PokemonIds.IVYSAUR: "Ivysaur", + PokemonIds.VENUSAUR: "Venusaur", + PokemonIds.CHARMANDER: "Charmander", + PokemonIds.CHARMELEON: "Charmeleon", + PokemonIds.CHARIZARD: "Charizard", + PokemonIds.SQUIRTLE: "Squirtle", + PokemonIds.WARTORTLE: "Wartortle", + PokemonIds.BLASTOISE: "Blastoise", + PokemonIds.CATERPIE: "Caterpie", + PokemonIds.METAPOD: "Metapod", + PokemonIds.BUTTERFREE: "Butterfree", + PokemonIds.CATERPIE: "Weedle", + PokemonIds.KAKUNA: "Kakuna", + PokemonIds.BEEDRILL: "Beedrill", + PokemonIds.PIDGEY: "Pidgey", + PokemonIds.PIDGEOTTO: "Pidgeotto", + PokemonIds.PIDGEOT: "Pidgeot", + PokemonIds.RATTATA: "Rattata", + PokemonIds.RATICATE: "Raticate", + PokemonIds.SPEAROW: "Spearow", + PokemonIds.FEAROW: "Fearow", + PokemonIds.EKANS: "Ekans", + PokemonIds.ARBOK: "Arbok", + PokemonIds.PIKACHU: "Pikachu", + PokemonIds.RAICHU: "Raichu", + PokemonIds.SANDSHREW: "Sandshrew", + PokemonIds.SANDSLASH: "Sandslash", + PokemonIds.NIDORAN_F: "Nidoran♀", + PokemonIds.NIDORINA: "Nidorina", + PokemonIds.NIDOQUEEN: "Nidoqueen", + PokemonIds.NIDORAN_M: "Nidoran♂", + PokemonIds.NIDORINO: "Nidorino", + PokemonIds.NIDOKING: "Nidoking", + PokemonIds.CLEFAIRY: "Clefairy", + PokemonIds.CLEFABLE: "Clefable", + PokemonIds.VULPIX: "Vulpix", + PokemonIds.NINETALES: "Ninetales", + PokemonIds.JIGGLYPUFF: "Jigglypuff", + PokemonIds.WIGGLYTUFF: "Wigglytuff", + PokemonIds.ZUBAT: "Zubat", + PokemonIds.GOLBAT: "Golbat", + PokemonIds.ODDISH: "Oddish", + PokemonIds.GLOOM: "Gloom", + PokemonIds.VILEPLUME: "Vileplume", + PokemonIds.PARAS: "Paras", + PokemonIds.PARASECT: "Parasect", + PokemonIds.VENONAT: "Venonat", + PokemonIds.VENOMOTH: "Venomoth", + PokemonIds.DIGLETT: "Diglett", + PokemonIds.DUGTRIO: "Dugtrio", + PokemonIds.MEOWTH: "Meowth", + PokemonIds.PERSIAN: "Persian", + PokemonIds.PSYDUCK: "Psyduck", + PokemonIds.GOLDUCK: "Golduck", + PokemonIds.MANKEY: "Mankey", + PokemonIds.PRIMEAPE: "Primeape", + PokemonIds.GROWLITHE: "Growlithe", + PokemonIds.ARCANINE: "Arcanine", + PokemonIds.POLIWAG: "Poliwag", + PokemonIds.POLIWHIRL: "Poliwhirl", + PokemonIds.POLIWRATH: "Poliwrath", + PokemonIds.ABRA: "Abra", + PokemonIds.KADABRA: "Kadabra", + PokemonIds.ALAKAZAM: "Alakazam", + PokemonIds.MACHOP: "Machop", + PokemonIds.MACHOKE: "Machoke", + PokemonIds.MACHAMP: "Machamp", + PokemonIds.BELLSPROUT: "Bellsprout", + PokemonIds.WEEPINBELL: "Weepinbell", + PokemonIds.VICTREEBEL: "Victreebel", + PokemonIds.TENTACOOL: "Tentacool", + PokemonIds.TENTACRUEL: "Tentacruel", + PokemonIds.GEODUDE: "Geodude", + PokemonIds.GRAVELER: "Graveler", + PokemonIds.GOLEM: "Golem", + PokemonIds.PONYTA: "Ponyta", + PokemonIds.RAPIDASH: "Rapidash", + PokemonIds.SLOWPOKE: "Slowpoke", + PokemonIds.SLOWBRO: "Slowbro", + PokemonIds.MAGNEMITE: "Magnemite", + PokemonIds.MAGNETON: "Magneton", + PokemonIds.FARFETCHD: "Farfetch’d", + PokemonIds.DODUO: "Doduo", + PokemonIds.DODRIO: "Dodrio", + PokemonIds.SEEL: "Seel", + PokemonIds.DEWGONG: "Dewgong", + PokemonIds.GRIMER: "Grimer", + PokemonIds.MUK: "Muk", + PokemonIds.SHELLDER: "Shellder", + PokemonIds.CLOYSTER: "Cloyster", + PokemonIds.GASTLY: "Gastly", + PokemonIds.HAUNTER: "Haunter", + PokemonIds.GENGAR: "Gengar", + PokemonIds.ONIX: "Onix", + PokemonIds.DROWZEE: "Drowzee", + PokemonIds.HYPNO: "Hypno", + PokemonIds.KRABBY: "Krabby", + PokemonIds.KINGLER: "Kingler", + PokemonIds.VOLTORB: "Voltorb", + PokemonIds.ELECTRODE: "Electrode", + PokemonIds.EXEGGCUTE: "Exeggcute", + PokemonIds.EXEGGUTOR: "Exeggutor", + PokemonIds.CUBONE: "Cubone", + PokemonIds.MAROWAK: "Marowak", + PokemonIds.HITMONLEE: "Hitmonlee", + PokemonIds.HITMONCHAN: "Hitmonchan", + PokemonIds.LICKITUNG: "Lickitung", + PokemonIds.KOFFING: "Koffing", + PokemonIds.WEEZING: "Weezing", + PokemonIds.RHYHORN: "Rhyhorn", + PokemonIds.RHYDON: "Rhydon", + PokemonIds.CHANSEY: "Chansey", + PokemonIds.TANGELA: "Tangela", + PokemonIds.KANGASKHAN: "Kangaskhan", + PokemonIds.HORSEA: "Horsea", + PokemonIds.SEADRA: "Seadra", + PokemonIds.GOLDEEN: "Goldeen", + PokemonIds.SEAKING: "Seaking", + PokemonIds.STARYU: "Staryu", + PokemonIds.STARMIE: "Starmie", + PokemonIds.MR_MIME: "Mr. Mime", + PokemonIds.SCYTHER: "Scyther", + PokemonIds.JYNX: "Jynx", + PokemonIds.ELECTABUZZ: "Electabuzz", + PokemonIds.MAGMAR: "Magmar", + PokemonIds.PINSIR: "Pinsir", + PokemonIds.TAUROS: "Tauros", + PokemonIds.MAGIKARP: "Magikarp", + PokemonIds.GYARADOS: "Gyarados", + PokemonIds.LAPRAS: "Lapras", + PokemonIds.DITTO: "Ditto", + PokemonIds.EEVEE: "Eevee", + PokemonIds.VAPOREON: "Vaporeon", + PokemonIds.JOLTEON: "Jolteon", + PokemonIds.FLAREON: "Flareon", + PokemonIds.PORYGON: "Porygon", + PokemonIds.OMANYTE: "Omanyte", + PokemonIds.OMASTAR: "Omastar", + PokemonIds.KABUTO: "Kabuto", + PokemonIds.KABUTOPS: "Kabutops", + PokemonIds.AERODACTYL: "Aerodactyl", + PokemonIds.SNORLAX: "Snorlax", + PokemonIds.ARTICUNO: "Articuno", + PokemonIds.ZAPDOS: "Zapdos", + PokemonIds.MOLTRES: "Moltres", + PokemonIds.DRATINI: "Dratini", + PokemonIds.DRAGONAIR: "Dragonair", + PokemonIds.DRAGONITE: "Dragonite", + PokemonIds.MEWTWO: "Mewtwo", + PokemonIds.MEW: "Mew", } \ No newline at end of file From 02815d4a3780c7e7ef6029fd93de458f7f3b8d87 Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Mon, 6 Nov 2023 13:22:59 -0500 Subject: [PATCH 27/74] Continue fleshing out Pokemon class --- .../game_wrapper_pokemon_gen1/core/pokemon.py | 36 +++++++++++++++---- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py index 308e92292..17fba3d8c 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py @@ -1,4 +1,5 @@ from ..data.pokemon.memory import PokemonBaseAddrs, PokemonOffsets +from ..data.pokemon.constants import PokemonIds, _POKEMON_NAMES, _POKEMON_POKEDEX_INDEX class Pokemon: @@ -62,8 +63,21 @@ def __init__(self, self.speed = speed self.special = special - @classmethod - def _load_pokemon_from_address(self, pyboy, pokemon_base_address): + @property + def name(self): + return Pokemon.get_pokemon_name_from_id(self.pokemon_id) + + @staticmethod + def get_pokemon_name_from_id(pokemon_id): + return _POKEMON_NAMES.get(PokemonIds(pokemon_id)) + + @staticmethod + def get_pokedex_id_from_pokemon_id(pokemon_id): + return _POKEMON_POKEDEX_INDEX.get(PokemonIds(pokemon_id)) + + + @staticmethod + def _load_pokemon_from_address(pyboy, pokemon_base_address): pokemon_values = [] @@ -75,12 +89,20 @@ def _load_pokemon_from_address(self, pyboy, pokemon_base_address): return Pokemon(*pokemon_values) @classmethod - def load_pokemon_from_party(self, pyboy, party_location): + def load_pokemon_from_party(cls, pyboy, party_location): # party_location goes from 1 to 6 pokemon_base_address = list(PokemonBaseAddrs)[party_location-1].value - return self._load_pokemon_from_address(pyboy, pokemon_base_address) + return cls._load_pokemon_from_address(pyboy, pokemon_base_address) + + def _generate_move_str(self): + s = f"Moves:\n" + \ + f"\tMove 1: {self.move_1}\n" + \ + f"\tMove 2: {self.move_2}\n" + \ + f"\tMove 3: {self.move_3}\n" + \ + f"\tMove 4: {self.move_4}\n" + + return s def pretty_stringify(self): - s = ''' - - ''' \ No newline at end of file + s = f"{self.name}\n" + self._generate_move_str() + return s \ No newline at end of file From c93dd7b2a8851200e0ca09cfd74b3c889277bd52 Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Mon, 6 Nov 2023 14:29:50 -0500 Subject: [PATCH 28/74] Rename Locations enum to LocationIds --- .../data/locations/constants.py | 498 +++++++++--------- 1 file changed, 249 insertions(+), 249 deletions(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/locations/constants.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/locations/constants.py index b7c5af7e8..b2edf900f 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/data/locations/constants.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/locations/constants.py @@ -1,6 +1,6 @@ from enum import Enum -class Locations(Enum): +class LocationIds(Enum): PALLET_TOWN = 0x00 VIRIDIAN_CITY = 0x01 PEWTER_CITY = 0x02 @@ -251,252 +251,252 @@ class Locations(Enum): AGATHAS_ROOM = 0xF7 LOCATION_NAMES = { - Locations.PALLET_TOWN: 'PALLET TOWN', - Locations.VIRIDIAN_CITY: 'VIRIDIAN CITY', - Locations.PEWTER_CITY: 'PEWTER CITY', - Locations.CERULEAN_CITY: 'CERULEAN CITY', - Locations.LAVENDER_TOWN: 'LAVENDER TOWN', - Locations.VERMILION_CITY: 'VERMILION CITY', - Locations.CELADON_CITY: 'CELADON CITY', - Locations.FUCHSIA_CITY: 'FUCHSIA CITY', - Locations.CINNABAR_ISLAND: 'CINNABAR ISLAND', - Locations.INDIGO_PLATEAU: 'INDIGO PLATEAU', - Locations.SAFFRON_CITY: 'SAFFRON CITY', - Locations.UNUSED_MAP_0B: 'UNUSED MAP 0B', - Locations.ROUTE_1: 'ROUTE 1', - Locations.ROUTE_2: 'ROUTE 2', - Locations.ROUTE_3: 'ROUTE 3', - Locations.ROUTE_4: 'ROUTE 4', - Locations.ROUTE_5: 'ROUTE 5', - Locations.ROUTE_6: 'ROUTE 6', - Locations.ROUTE_7: 'ROUTE 7', - Locations.ROUTE_8: 'ROUTE 8', - Locations.ROUTE_9: 'ROUTE 9', - Locations.ROUTE_10: 'ROUTE 10', - Locations.ROUTE_11: 'ROUTE 11', - Locations.ROUTE_12: 'ROUTE 12', - Locations.ROUTE_13: 'ROUTE 13', - Locations.ROUTE_14: 'ROUTE 14', - Locations.ROUTE_15: 'ROUTE 15', - Locations.ROUTE_16: 'ROUTE 16', - Locations.ROUTE_17: 'ROUTE 17', - Locations.ROUTE_18: 'ROUTE 18', - Locations.ROUTE_19: 'ROUTE 19', - Locations.ROUTE_20: 'ROUTE 20', - Locations.ROUTE_21: 'ROUTE 21', - Locations.ROUTE_22: 'ROUTE 22', - Locations.ROUTE_23: 'ROUTE 23', - Locations.ROUTE_24: 'ROUTE 24', - Locations.ROUTE_25: 'ROUTE 25', - Locations.REDS_HOUSE_1F: 'RED\'S HOUSE 1F', - Locations.REDS_HOUSE_2F: 'RED\'S HOUSE 2F', - Locations.BLUES_HOUSE: 'BLUE\'S HOUSE', - Locations.OAKS_LAB: 'OAK\'S LAB', - Locations.VIRIDIAN_POKECENTER: 'VIRIDIAN POKECENTER', - Locations.VIRIDIAN_MART: 'VIRIDIAN MART', - Locations.VIRIDIAN_SCHOOL_HOUSE: 'VIRIDIAN SCHOOL HOUSE', - Locations.VIRIDIAN_NICKNAME_HOUSE: 'VIRIDIAN NICKNAME HOUSE', - Locations.VIRIDIAN_GYM: 'VIRIDIAN GYM', - Locations.DIGLETTS_CAVE_ROUTE_2: 'DIGLETTS CAVE ROUTE 2', - Locations.VIRIDIAN_FOREST_NORTH_GATE: 'VIRIDIAN FOREST NORTH GATE', - Locations.ROUTE_2_TRADE_HOUSE: 'ROUTE 2 TRADE HOUSE', - Locations.ROUTE_2_GATE: 'ROUTE 2 GATE', - Locations.VIRIDIAN_FOREST_SOUTH_GATE: 'VIRIDIAN FOREST SOUTH GATE', - Locations.VIRIDIAN_FOREST: 'VIRIDIAN FOREST', - Locations.MUSEUM_1F: 'MUSEUM 1F', - Locations.MUSEUM_2F: 'MUSEUM 2F', - Locations.PEWTER_GYM: 'PEWTER GYM', - Locations.PEWTER_NIDORAN_HOUSE: 'PEWTER NIDORAN HOUSE', - Locations.PEWTER_MART: 'PEWTER MART', - Locations.PEWTER_SPEECH_HOUSE: 'PEWTER SPEECH HOUSE', - Locations.PEWTER_POKECENTER: 'PEWTER POKECENTER', - Locations.MT_MOON_1F: 'MT MOON 1F', - Locations.MT_MOON_B1F: 'MT MOON B1F', - Locations.MT_MOON_B2F: 'MT MOON B2F', - Locations.CERULEAN_TRASHED_HOUSE: 'CERULEAN TRASHED HOUSE', - Locations.CERULEAN_TRADE_HOUSE: 'CERULEAN TRADE HOUSE', - Locations.CERULEAN_POKECENTER: 'CERULEAN POKECENTER', - Locations.CERULEAN_GYM: 'CERULEAN GYM', - Locations.BIKE_SHOP: 'BIKE SHOP', - Locations.CERULEAN_MART: 'CERULEAN MART', - Locations.MT_MOON_POKECENTER: 'MT MOON POKECENTER', - Locations.CERULEAN_TRASHED_HOUSE_COPY: 'CERULEAN TRASHED HOUSE COPY', - Locations.ROUTE_5_GATE: 'ROUTE 5 GATE', - Locations.UNDERGROUND_PATH_ROUTE_5: 'UNDERGROUND PATH ROUTE 5', - Locations.DAYCARE: 'DAYCARE', - Locations.ROUTE_6_GATE: 'ROUTE 6 GATE', - Locations.UNDERGROUND_PATH_ROUTE_6: 'UNDERGROUND PATH ROUTE 6', - Locations.UNDERGROUND_PATH_ROUTE_6_COPY: 'UNDERGROUND PATH ROUTE 6 COPY', - Locations.ROUTE_7_GATE: 'ROUTE 7 GATE', - Locations.UNDERGROUND_PATH_ROUTE_7: 'UNDERGROUND PATH ROUTE 7', - Locations.UNDERGROUND_PATH_ROUTE_7_COPY: 'UNDERGROUND PATH ROUTE 7 COPY', - Locations.ROUTE_8_GATE: 'ROUTE 8 GATE', - Locations.UNDERGROUND_PATH_ROUTE_8: 'UNDERGROUND PATH ROUTE 8', - Locations.ROCK_TUNNEL_POKECENTER: 'ROCK TUNNEL POKECENTER', - Locations.ROCK_TUNNEL_1F: 'ROCK TUNNEL 1F', - Locations.POWER_PLANT: 'POWER PLANT', - Locations.ROUTE_11_GATE_1F: 'ROUTE 11 GATE 1F', - Locations.DIGLETTS_CAVE_ROUTE_11: 'DIGLETT\'S CAVE ROUTE 11', - Locations.ROUTE_11_GATE_2F: 'ROUTE 11 GATE 2F', - Locations.ROUTE_12_GATE_1F: 'ROUTE 12 GATE 1F', - Locations.BILLS_HOUSE: 'BILLS HOUSE', - Locations.VERMILION_POKECENTER: 'VERMILION POKECENTER', - Locations.POKEMON_FAN_CLUB: 'POKEMON FAN CLUB', - Locations.VERMILION_MART: 'VERMILION MART', - Locations.VERMILION_GYM: 'VERMILION GYM', - Locations.VERMILION_PIDGEY_HOUSE: 'VERMILION PIDGEY HOUSE', - Locations.VERMILION_DOCK: 'VERMILION DOCK', - Locations.SS_ANNE_1F: 'SS ANNE 1F', - Locations.SS_ANNE_2F: 'SS ANNE 2F', - Locations.SS_ANNE_3F: 'SS ANNE 3F', - Locations.SS_ANNE_B1F: 'SS ANNE B1F', - Locations.SS_ANNE_BOW: 'SS ANNE BOW', - Locations.SS_ANNE_KITCHEN: 'SS ANNE KITCHEN', - Locations.SS_ANNE_CAPTAINS_ROOM: 'SS ANNE CAPTAIN\'S ROOM', - Locations.SS_ANNE_1F_ROOMS: 'SS ANNE 1F ROOMS', - Locations.SS_ANNE_2F_ROOMS: 'SS ANNE 2F ROOMS', - Locations.SS_ANNE_B1F_ROOMS: 'SS ANNE B1F ROOMS', - Locations.UNUSED_MAP_69: 'UNUSED MAP 69', - Locations.UNUSED_MAP_6A: 'UNUSED MAP 6A', - Locations.UNUSED_MAP_6B: 'UNUSED MAP 6B', - Locations.VICTORY_ROAD_1F: 'VICTORY ROAD 1F', - Locations.UNUSED_MAP_6D: 'UNUSED MAP 6D', - Locations.UNUSED_MAP_6E: 'UNUSED MAP 6E', - Locations.UNUSED_MAP_6F: 'UNUSED MAP 6F', - Locations.UNUSED_MAP_70: 'UNUSED MAP 70', - Locations.LANCES_ROOM: 'LANCES ROOM', - Locations.UNUSED_MAP_72: 'UNUSED MAP 72', - Locations.UNUSED_MAP_73: 'UNUSED MAP 73', - Locations.UNUSED_MAP_74: 'UNUSED MAP 74', - Locations.UNUSED_MAP_75: 'UNUSED MAP 75', - Locations.HALL_OF_FAME: 'HALL OF FAME', - Locations.UNDERGROUND_PATH_NORTH_SOUTH: 'UNDERGROUND PATH NORTH SOUTH', - Locations.CHAMPIONS_ROOM: 'CHAMPION\'S ROOM', - Locations.UNDERGROUND_PATH_WEST_EAST: 'UNDERGROUND PATH WEST EAST', - Locations.CELADON_MART_1F: 'CELADON MART 1F', - Locations.CELADON_MART_2F: 'CELADON MART 2F', - Locations.CELADON_MART_3F: 'CELADON MART 3F', - Locations.CELADON_MART_4F: 'CELADON MART 4F', - Locations.CELADON_MART_ROOF: 'CELADON MART ROOF', - Locations.CELADON_MART_ELEVATOR: 'CELADON MART ELEVATOR', - Locations.CELADON_MANSION_1F: 'CELADON MANSION 1F', - Locations.CELADON_MANSION_2F: 'CELADON MANSION 2F', - Locations.CELADON_MANSION_3F: 'CELADON MANSION 3F', - Locations.CELADON_MANSION_ROOF: 'CELADON MANSION ROOF', - Locations.CELADON_MANSION_ROOF_HOUSE: 'CELADON MANSION ROOF HOUSE', - Locations.CELADON_POKECENTER: 'CELADON POKECENTER', - Locations.CELADON_GYM: 'CELADON GYM', - Locations.GAME_CORNER: 'GAME CORNER', - Locations.CELADON_MART_5F: 'CELADON MART 5F', - Locations.GAME_CORNER_PRIZE_ROOM: 'GAME CORNER PRIZE ROOM', - Locations.CELADON_DINER: 'CELADON DINER', - Locations.CELADON_CHIEF_HOUSE: 'CELADON CHIEF HOUSE', - Locations.CELADON_HOTEL: 'CELADON HOTEL', - Locations.LAVENDER_POKECENTER: 'LAVENDER POKECENTER', - Locations.POKEMON_TOWER_1F: 'POKEMON TOWER 1F', - Locations.POKEMON_TOWER_2F: 'POKEMON TOWER 2F', - Locations.POKEMON_TOWER_3F: 'POKEMON TOWER 3F', - Locations.POKEMON_TOWER_4F: 'POKEMON TOWER 4F', - Locations.POKEMON_TOWER_5F: 'POKEMON TOWER 5F', - Locations.POKEMON_TOWER_6F: 'POKEMON TOWER 6F', - Locations.POKEMON_TOWER_7F: 'POKEMON TOWER 7F', - Locations.MR_FUJIS_HOUSE: 'MR FUJIS HOUSE', - Locations.LAVENDER_MART: 'LAVENDER MART', - Locations.LAVENDER_CUBONE_HOUSE: 'LAVENDER CUBONE HOUSE', - Locations.FUCHSIA_MART: 'FUCHSIA MART', - Locations.FUCHSIA_BILLS_GRANDPAS_HOUSE: 'FUCHSIA BILL\'S GRANDPAS HOUSE', - Locations.FUCHSIA_POKECENTER: 'FUCHSIA POKECENTER', - Locations.WARDENS_HOUSE: 'WARDENS HOUSE', - Locations.SAFARI_ZONE_GATE: 'SAFARI ZONE GATE', - Locations.FUCHSIA_GYM: 'FUCHSIA GYM', - Locations.FUCHSIA_MEETING_ROOM: 'FUCHSIA MEETING ROOM', - Locations.SEAFOAM_ISLANDS_B1F: 'SEAFOAM ISLANDS B1F', - Locations.SEAFOAM_ISLANDS_B2F: 'SEAFOAM ISLANDS B2F', - Locations.SEAFOAM_ISLANDS_B3F: 'SEAFOAM ISLANDS B3F', - Locations.SEAFOAM_ISLANDS_B4F: 'SEAFOAM ISLANDS B4F', - Locations.VERMILION_OLD_ROD_HOUSE: 'VERMILION OLD ROD HOUSE', - Locations.FUCHSIA_GOOD_ROD_HOUSE: 'FUCHSIA GOOD ROD HOUSE', - Locations.POKEMON_MANSION_1F: 'POKEMON MANSION 1F', - Locations.CINNABAR_GYM: 'CINNABAR GYM', - Locations.CINNABAR_LAB: 'CINNABAR LAB', - Locations.CINNABAR_LAB_TRADE_ROOM: 'CINNABAR LAB TRADE ROOM', - Locations.CINNABAR_LAB_METRONOME_ROOM: 'CINNABAR LAB METRONOME ROOM', - Locations.CINNABAR_LAB_FOSSIL_ROOM: 'CINNABAR LAB FOSSIL ROOM', - Locations.CINNABAR_POKECENTER: 'CINNABAR POKECENTER', - Locations.CINNABAR_MART: 'CINNABAR MART', - Locations.CINNABAR_MART_COPY: 'CINNABAR MART COPY', - Locations.INDIGO_PLATEAU_LOBBY: 'INDIGO PLATEAU LOBBY', - Locations.COPYCATS_HOUSE_1F: 'COPYCATS HOUSE 1F', - Locations.COPYCATS_HOUSE_2F: 'COPYCATS HOUSE 2F', - Locations.FIGHTING_DOJO: 'FIGHTING DOJO', - Locations.SAFFRON_GYM: 'SAFFRON GYM', - Locations.SAFFRON_PIDGEY_HOUSE: 'SAFFRON PIDGEY HOUSE', - Locations.SAFFRON_MART: 'SAFFRON MART', - Locations.SILPH_CO_1F: 'SILPH CO 1F', - Locations.SAFFRON_POKECENTER: 'SAFFRON POKECENTER', - Locations.MR_PSYCHICS_HOUSE: 'MR PSYCHICS HOUSE', - Locations.ROUTE_15_GATE_1F: 'ROUTE 15 GATE 1F', - Locations.ROUTE_15_GATE_2F: 'ROUTE 15 GATE 2F', - Locations.ROUTE_16_GATE_1F: 'ROUTE 16 GATE 1F', - Locations.ROUTE_16_GATE_2F: 'ROUTE 16 GATE 2F', - Locations.ROUTE_16_FLY_HOUSE: 'ROUTE 16 FLY HOUSE', - Locations.ROUTE_12_SUPER_ROD_HOUSE: 'ROUTE 12 SUPER ROD HOUSE', - Locations.ROUTE_18_GATE_1F: 'ROUTE 18 GATE 1F', - Locations.ROUTE_18_GATE_2F: 'ROUTE 18 GATE 2F', - Locations.SEAFOAM_ISLANDS_1F: 'SEAFOAM ISLANDS 1F', - Locations.ROUTE_22_GATE: 'ROUTE 22 GATE', - Locations.VICTORY_ROAD_2F: 'VICTORY ROAD 2F', - Locations.ROUTE_12_GATE_2F: 'ROUTE 12 GATE 2F', - Locations.VERMILION_TRADE_HOUSE: 'VERMILION TRADE HOUSE', - Locations.DIGLETTS_CAVE: 'DIGLETTS CAVE', - Locations.VICTORY_ROAD_3F: 'VICTORY ROAD 3F', - Locations.ROCKET_HIDEOUT_B1F: 'ROCKET HIDEOUT B1F', - Locations.ROCKET_HIDEOUT_B2F: 'ROCKET HIDEOUT B2F', - Locations.ROCKET_HIDEOUT_B3F: 'ROCKET HIDEOUT B3F', - Locations.ROCKET_HIDEOUT_B4F: 'ROCKET HIDEOUT B4F', - Locations.ROCKET_HIDEOUT_ELEVATOR: 'ROCKET HIDEOUT ELEVATOR', - Locations.UNUSED_MAP_CC: 'UNUSED MAP CC', - Locations.UNUSED_MAP_CD: 'UNUSED MAP CD', - Locations.UNUSED_MAP_CE: 'UNUSED MAP CE', - Locations.SILPH_CO_2F: 'SILPH CO 2F', - Locations.SILPH_CO_3F: 'SILPH CO 3F', - Locations.SILPH_CO_4F: 'SILPH CO 4F', - Locations.SILPH_CO_5F: 'SILPH CO 5F', - Locations.SILPH_CO_6F: 'SILPH CO 6F', - Locations.SILPH_CO_7F: 'SILPH CO 7F', - Locations.SILPH_CO_8F: 'SILPH CO 8F', - Locations.POKEMON_MANSION_2F: 'POKEMON MANSION 2F', - Locations.POKEMON_MANSION_3F: 'POKEMON MANSION 3F', - Locations.POKEMON_MANSION_B1F: 'POKEMON MANSION B1F', - Locations.SAFARI_ZONE_EAST: 'SAFARI ZONE EAST', - Locations.SAFARI_ZONE_NORTH: 'SAFARI ZONE NORTH', - Locations.SAFARI_ZONE_WEST: 'SAFARI ZONE WEST', - Locations.SAFARI_ZONE_CENTER: 'SAFARI ZONE CENTER', - Locations.SAFARI_ZONE_CENTER_REST_HOUSE: 'SAFARI ZONE CENTER REST HOUSE', - Locations.SAFARI_ZONE_SECRET_HOUSE: 'SAFARI ZONE SECRET HOUSE', - Locations.SAFARI_ZONE_WEST_REST_HOUSE: 'SAFARI ZONE WEST REST HOUSE', - Locations.SAFARI_ZONE_EAST_REST_HOUSE: 'SAFARI ZONE EAST REST HOUSE', - Locations.SAFARI_ZONE_NORTH_REST_HOUSE: 'SAFARI ZONE NORTH REST HOUSE', - Locations.CERULEAN_CAVE_2F: 'CERULEAN CAVE 2F', - Locations.CERULEAN_CAVE_B1F: 'CERULEAN CAVE B1F', - Locations.CERULEAN_CAVE_1F: 'CERULEAN CAVE 1F', - Locations.NAME_RATERS_HOUSE: 'NAME RATER\'S HOUSE', - Locations.CERULEAN_BADGE_HOUSE: 'CERULEAN BADGE HOUSE', - Locations.UNUSED_MAP_E7: 'UNUSED MAP E7', - Locations.ROCK_TUNNEL_B1F: 'ROCK TUNNEL B1F', - Locations.SILPH_CO_9F: 'SILPH CO 9F', - Locations.SILPH_CO_10F: 'SILPH CO 10F', - Locations.SILPH_CO_11F: 'SILPH CO 11F', - Locations.SILPH_CO_ELEVATOR: 'SILPH CO ELEVATOR', - Locations.UNUSED_MAP_ED: 'UNUSED MAP ED', - Locations.UNUSED_MAP_EE: 'UNUSED MAP EE', - Locations.TRADE_CENTER: 'TRADE CENTER', - Locations.COLOSSEUM: 'COLOSSEUM', - Locations.UNUSED_MAP_F1: 'UNUSED MAP F1', - Locations.UNUSED_MAP_F2: 'UNUSED MAP F2', - Locations.UNUSED_MAP_F3: 'UNUSED MAP F3', - Locations.UNUSED_MAP_F4: 'UNUSED MAP F4', - Locations.LORELEIS_ROOM: 'LORELEI\'S ROOM', - Locations.BRUNOS_ROOM: 'BRUNO\'S ROOM', - Locations.AGATHAS_ROOM: 'AGATHA\'S ROOM', + LocationIds.PALLET_TOWN: 'PALLET TOWN', + LocationIds.VIRIDIAN_CITY: 'VIRIDIAN CITY', + LocationIds.PEWTER_CITY: 'PEWTER CITY', + LocationIds.CERULEAN_CITY: 'CERULEAN CITY', + LocationIds.LAVENDER_TOWN: 'LAVENDER TOWN', + LocationIds.VERMILION_CITY: 'VERMILION CITY', + LocationIds.CELADON_CITY: 'CELADON CITY', + LocationIds.FUCHSIA_CITY: 'FUCHSIA CITY', + LocationIds.CINNABAR_ISLAND: 'CINNABAR ISLAND', + LocationIds.INDIGO_PLATEAU: 'INDIGO PLATEAU', + LocationIds.SAFFRON_CITY: 'SAFFRON CITY', + LocationIds.UNUSED_MAP_0B: 'UNUSED MAP 0B', + LocationIds.ROUTE_1: 'ROUTE 1', + LocationIds.ROUTE_2: 'ROUTE 2', + LocationIds.ROUTE_3: 'ROUTE 3', + LocationIds.ROUTE_4: 'ROUTE 4', + LocationIds.ROUTE_5: 'ROUTE 5', + LocationIds.ROUTE_6: 'ROUTE 6', + LocationIds.ROUTE_7: 'ROUTE 7', + LocationIds.ROUTE_8: 'ROUTE 8', + LocationIds.ROUTE_9: 'ROUTE 9', + LocationIds.ROUTE_10: 'ROUTE 10', + LocationIds.ROUTE_11: 'ROUTE 11', + LocationIds.ROUTE_12: 'ROUTE 12', + LocationIds.ROUTE_13: 'ROUTE 13', + LocationIds.ROUTE_14: 'ROUTE 14', + LocationIds.ROUTE_15: 'ROUTE 15', + LocationIds.ROUTE_16: 'ROUTE 16', + LocationIds.ROUTE_17: 'ROUTE 17', + LocationIds.ROUTE_18: 'ROUTE 18', + LocationIds.ROUTE_19: 'ROUTE 19', + LocationIds.ROUTE_20: 'ROUTE 20', + LocationIds.ROUTE_21: 'ROUTE 21', + LocationIds.ROUTE_22: 'ROUTE 22', + LocationIds.ROUTE_23: 'ROUTE 23', + LocationIds.ROUTE_24: 'ROUTE 24', + LocationIds.ROUTE_25: 'ROUTE 25', + LocationIds.REDS_HOUSE_1F: 'RED\'S HOUSE 1F', + LocationIds.REDS_HOUSE_2F: 'RED\'S HOUSE 2F', + LocationIds.BLUES_HOUSE: 'BLUE\'S HOUSE', + LocationIds.OAKS_LAB: 'OAK\'S LAB', + LocationIds.VIRIDIAN_POKECENTER: 'VIRIDIAN POKECENTER', + LocationIds.VIRIDIAN_MART: 'VIRIDIAN MART', + LocationIds.VIRIDIAN_SCHOOL_HOUSE: 'VIRIDIAN SCHOOL HOUSE', + LocationIds.VIRIDIAN_NICKNAME_HOUSE: 'VIRIDIAN NICKNAME HOUSE', + LocationIds.VIRIDIAN_GYM: 'VIRIDIAN GYM', + LocationIds.DIGLETTS_CAVE_ROUTE_2: 'DIGLETTS CAVE ROUTE 2', + LocationIds.VIRIDIAN_FOREST_NORTH_GATE: 'VIRIDIAN FOREST NORTH GATE', + LocationIds.ROUTE_2_TRADE_HOUSE: 'ROUTE 2 TRADE HOUSE', + LocationIds.ROUTE_2_GATE: 'ROUTE 2 GATE', + LocationIds.VIRIDIAN_FOREST_SOUTH_GATE: 'VIRIDIAN FOREST SOUTH GATE', + LocationIds.VIRIDIAN_FOREST: 'VIRIDIAN FOREST', + LocationIds.MUSEUM_1F: 'MUSEUM 1F', + LocationIds.MUSEUM_2F: 'MUSEUM 2F', + LocationIds.PEWTER_GYM: 'PEWTER GYM', + LocationIds.PEWTER_NIDORAN_HOUSE: 'PEWTER NIDORAN HOUSE', + LocationIds.PEWTER_MART: 'PEWTER MART', + LocationIds.PEWTER_SPEECH_HOUSE: 'PEWTER SPEECH HOUSE', + LocationIds.PEWTER_POKECENTER: 'PEWTER POKECENTER', + LocationIds.MT_MOON_1F: 'MT MOON 1F', + LocationIds.MT_MOON_B1F: 'MT MOON B1F', + LocationIds.MT_MOON_B2F: 'MT MOON B2F', + LocationIds.CERULEAN_TRASHED_HOUSE: 'CERULEAN TRASHED HOUSE', + LocationIds.CERULEAN_TRADE_HOUSE: 'CERULEAN TRADE HOUSE', + LocationIds.CERULEAN_POKECENTER: 'CERULEAN POKECENTER', + LocationIds.CERULEAN_GYM: 'CERULEAN GYM', + LocationIds.BIKE_SHOP: 'BIKE SHOP', + LocationIds.CERULEAN_MART: 'CERULEAN MART', + LocationIds.MT_MOON_POKECENTER: 'MT MOON POKECENTER', + LocationIds.CERULEAN_TRASHED_HOUSE_COPY: 'CERULEAN TRASHED HOUSE COPY', + LocationIds.ROUTE_5_GATE: 'ROUTE 5 GATE', + LocationIds.UNDERGROUND_PATH_ROUTE_5: 'UNDERGROUND PATH ROUTE 5', + LocationIds.DAYCARE: 'DAYCARE', + LocationIds.ROUTE_6_GATE: 'ROUTE 6 GATE', + LocationIds.UNDERGROUND_PATH_ROUTE_6: 'UNDERGROUND PATH ROUTE 6', + LocationIds.UNDERGROUND_PATH_ROUTE_6_COPY: 'UNDERGROUND PATH ROUTE 6 COPY', + LocationIds.ROUTE_7_GATE: 'ROUTE 7 GATE', + LocationIds.UNDERGROUND_PATH_ROUTE_7: 'UNDERGROUND PATH ROUTE 7', + LocationIds.UNDERGROUND_PATH_ROUTE_7_COPY: 'UNDERGROUND PATH ROUTE 7 COPY', + LocationIds.ROUTE_8_GATE: 'ROUTE 8 GATE', + LocationIds.UNDERGROUND_PATH_ROUTE_8: 'UNDERGROUND PATH ROUTE 8', + LocationIds.ROCK_TUNNEL_POKECENTER: 'ROCK TUNNEL POKECENTER', + LocationIds.ROCK_TUNNEL_1F: 'ROCK TUNNEL 1F', + LocationIds.POWER_PLANT: 'POWER PLANT', + LocationIds.ROUTE_11_GATE_1F: 'ROUTE 11 GATE 1F', + LocationIds.DIGLETTS_CAVE_ROUTE_11: 'DIGLETT\'S CAVE ROUTE 11', + LocationIds.ROUTE_11_GATE_2F: 'ROUTE 11 GATE 2F', + LocationIds.ROUTE_12_GATE_1F: 'ROUTE 12 GATE 1F', + LocationIds.BILLS_HOUSE: 'BILLS HOUSE', + LocationIds.VERMILION_POKECENTER: 'VERMILION POKECENTER', + LocationIds.POKEMON_FAN_CLUB: 'POKEMON FAN CLUB', + LocationIds.VERMILION_MART: 'VERMILION MART', + LocationIds.VERMILION_GYM: 'VERMILION GYM', + LocationIds.VERMILION_PIDGEY_HOUSE: 'VERMILION PIDGEY HOUSE', + LocationIds.VERMILION_DOCK: 'VERMILION DOCK', + LocationIds.SS_ANNE_1F: 'SS ANNE 1F', + LocationIds.SS_ANNE_2F: 'SS ANNE 2F', + LocationIds.SS_ANNE_3F: 'SS ANNE 3F', + LocationIds.SS_ANNE_B1F: 'SS ANNE B1F', + LocationIds.SS_ANNE_BOW: 'SS ANNE BOW', + LocationIds.SS_ANNE_KITCHEN: 'SS ANNE KITCHEN', + LocationIds.SS_ANNE_CAPTAINS_ROOM: 'SS ANNE CAPTAIN\'S ROOM', + LocationIds.SS_ANNE_1F_ROOMS: 'SS ANNE 1F ROOMS', + LocationIds.SS_ANNE_2F_ROOMS: 'SS ANNE 2F ROOMS', + LocationIds.SS_ANNE_B1F_ROOMS: 'SS ANNE B1F ROOMS', + LocationIds.UNUSED_MAP_69: 'UNUSED MAP 69', + LocationIds.UNUSED_MAP_6A: 'UNUSED MAP 6A', + LocationIds.UNUSED_MAP_6B: 'UNUSED MAP 6B', + LocationIds.VICTORY_ROAD_1F: 'VICTORY ROAD 1F', + LocationIds.UNUSED_MAP_6D: 'UNUSED MAP 6D', + LocationIds.UNUSED_MAP_6E: 'UNUSED MAP 6E', + LocationIds.UNUSED_MAP_6F: 'UNUSED MAP 6F', + LocationIds.UNUSED_MAP_70: 'UNUSED MAP 70', + LocationIds.LANCES_ROOM: 'LANCES ROOM', + LocationIds.UNUSED_MAP_72: 'UNUSED MAP 72', + LocationIds.UNUSED_MAP_73: 'UNUSED MAP 73', + LocationIds.UNUSED_MAP_74: 'UNUSED MAP 74', + LocationIds.UNUSED_MAP_75: 'UNUSED MAP 75', + LocationIds.HALL_OF_FAME: 'HALL OF FAME', + LocationIds.UNDERGROUND_PATH_NORTH_SOUTH: 'UNDERGROUND PATH NORTH SOUTH', + LocationIds.CHAMPIONS_ROOM: 'CHAMPION\'S ROOM', + LocationIds.UNDERGROUND_PATH_WEST_EAST: 'UNDERGROUND PATH WEST EAST', + LocationIds.CELADON_MART_1F: 'CELADON MART 1F', + LocationIds.CELADON_MART_2F: 'CELADON MART 2F', + LocationIds.CELADON_MART_3F: 'CELADON MART 3F', + LocationIds.CELADON_MART_4F: 'CELADON MART 4F', + LocationIds.CELADON_MART_ROOF: 'CELADON MART ROOF', + LocationIds.CELADON_MART_ELEVATOR: 'CELADON MART ELEVATOR', + LocationIds.CELADON_MANSION_1F: 'CELADON MANSION 1F', + LocationIds.CELADON_MANSION_2F: 'CELADON MANSION 2F', + LocationIds.CELADON_MANSION_3F: 'CELADON MANSION 3F', + LocationIds.CELADON_MANSION_ROOF: 'CELADON MANSION ROOF', + LocationIds.CELADON_MANSION_ROOF_HOUSE: 'CELADON MANSION ROOF HOUSE', + LocationIds.CELADON_POKECENTER: 'CELADON POKECENTER', + LocationIds.CELADON_GYM: 'CELADON GYM', + LocationIds.GAME_CORNER: 'GAME CORNER', + LocationIds.CELADON_MART_5F: 'CELADON MART 5F', + LocationIds.GAME_CORNER_PRIZE_ROOM: 'GAME CORNER PRIZE ROOM', + LocationIds.CELADON_DINER: 'CELADON DINER', + LocationIds.CELADON_CHIEF_HOUSE: 'CELADON CHIEF HOUSE', + LocationIds.CELADON_HOTEL: 'CELADON HOTEL', + LocationIds.LAVENDER_POKECENTER: 'LAVENDER POKECENTER', + LocationIds.POKEMON_TOWER_1F: 'POKEMON TOWER 1F', + LocationIds.POKEMON_TOWER_2F: 'POKEMON TOWER 2F', + LocationIds.POKEMON_TOWER_3F: 'POKEMON TOWER 3F', + LocationIds.POKEMON_TOWER_4F: 'POKEMON TOWER 4F', + LocationIds.POKEMON_TOWER_5F: 'POKEMON TOWER 5F', + LocationIds.POKEMON_TOWER_6F: 'POKEMON TOWER 6F', + LocationIds.POKEMON_TOWER_7F: 'POKEMON TOWER 7F', + LocationIds.MR_FUJIS_HOUSE: 'MR FUJIS HOUSE', + LocationIds.LAVENDER_MART: 'LAVENDER MART', + LocationIds.LAVENDER_CUBONE_HOUSE: 'LAVENDER CUBONE HOUSE', + LocationIds.FUCHSIA_MART: 'FUCHSIA MART', + LocationIds.FUCHSIA_BILLS_GRANDPAS_HOUSE: 'FUCHSIA BILL\'S GRANDPAS HOUSE', + LocationIds.FUCHSIA_POKECENTER: 'FUCHSIA POKECENTER', + LocationIds.WARDENS_HOUSE: 'WARDENS HOUSE', + LocationIds.SAFARI_ZONE_GATE: 'SAFARI ZONE GATE', + LocationIds.FUCHSIA_GYM: 'FUCHSIA GYM', + LocationIds.FUCHSIA_MEETING_ROOM: 'FUCHSIA MEETING ROOM', + LocationIds.SEAFOAM_ISLANDS_B1F: 'SEAFOAM ISLANDS B1F', + LocationIds.SEAFOAM_ISLANDS_B2F: 'SEAFOAM ISLANDS B2F', + LocationIds.SEAFOAM_ISLANDS_B3F: 'SEAFOAM ISLANDS B3F', + LocationIds.SEAFOAM_ISLANDS_B4F: 'SEAFOAM ISLANDS B4F', + LocationIds.VERMILION_OLD_ROD_HOUSE: 'VERMILION OLD ROD HOUSE', + LocationIds.FUCHSIA_GOOD_ROD_HOUSE: 'FUCHSIA GOOD ROD HOUSE', + LocationIds.POKEMON_MANSION_1F: 'POKEMON MANSION 1F', + LocationIds.CINNABAR_GYM: 'CINNABAR GYM', + LocationIds.CINNABAR_LAB: 'CINNABAR LAB', + LocationIds.CINNABAR_LAB_TRADE_ROOM: 'CINNABAR LAB TRADE ROOM', + LocationIds.CINNABAR_LAB_METRONOME_ROOM: 'CINNABAR LAB METRONOME ROOM', + LocationIds.CINNABAR_LAB_FOSSIL_ROOM: 'CINNABAR LAB FOSSIL ROOM', + LocationIds.CINNABAR_POKECENTER: 'CINNABAR POKECENTER', + LocationIds.CINNABAR_MART: 'CINNABAR MART', + LocationIds.CINNABAR_MART_COPY: 'CINNABAR MART COPY', + LocationIds.INDIGO_PLATEAU_LOBBY: 'INDIGO PLATEAU LOBBY', + LocationIds.COPYCATS_HOUSE_1F: 'COPYCATS HOUSE 1F', + LocationIds.COPYCATS_HOUSE_2F: 'COPYCATS HOUSE 2F', + LocationIds.FIGHTING_DOJO: 'FIGHTING DOJO', + LocationIds.SAFFRON_GYM: 'SAFFRON GYM', + LocationIds.SAFFRON_PIDGEY_HOUSE: 'SAFFRON PIDGEY HOUSE', + LocationIds.SAFFRON_MART: 'SAFFRON MART', + LocationIds.SILPH_CO_1F: 'SILPH CO 1F', + LocationIds.SAFFRON_POKECENTER: 'SAFFRON POKECENTER', + LocationIds.MR_PSYCHICS_HOUSE: 'MR PSYCHICS HOUSE', + LocationIds.ROUTE_15_GATE_1F: 'ROUTE 15 GATE 1F', + LocationIds.ROUTE_15_GATE_2F: 'ROUTE 15 GATE 2F', + LocationIds.ROUTE_16_GATE_1F: 'ROUTE 16 GATE 1F', + LocationIds.ROUTE_16_GATE_2F: 'ROUTE 16 GATE 2F', + LocationIds.ROUTE_16_FLY_HOUSE: 'ROUTE 16 FLY HOUSE', + LocationIds.ROUTE_12_SUPER_ROD_HOUSE: 'ROUTE 12 SUPER ROD HOUSE', + LocationIds.ROUTE_18_GATE_1F: 'ROUTE 18 GATE 1F', + LocationIds.ROUTE_18_GATE_2F: 'ROUTE 18 GATE 2F', + LocationIds.SEAFOAM_ISLANDS_1F: 'SEAFOAM ISLANDS 1F', + LocationIds.ROUTE_22_GATE: 'ROUTE 22 GATE', + LocationIds.VICTORY_ROAD_2F: 'VICTORY ROAD 2F', + LocationIds.ROUTE_12_GATE_2F: 'ROUTE 12 GATE 2F', + LocationIds.VERMILION_TRADE_HOUSE: 'VERMILION TRADE HOUSE', + LocationIds.DIGLETTS_CAVE: 'DIGLETTS CAVE', + LocationIds.VICTORY_ROAD_3F: 'VICTORY ROAD 3F', + LocationIds.ROCKET_HIDEOUT_B1F: 'ROCKET HIDEOUT B1F', + LocationIds.ROCKET_HIDEOUT_B2F: 'ROCKET HIDEOUT B2F', + LocationIds.ROCKET_HIDEOUT_B3F: 'ROCKET HIDEOUT B3F', + LocationIds.ROCKET_HIDEOUT_B4F: 'ROCKET HIDEOUT B4F', + LocationIds.ROCKET_HIDEOUT_ELEVATOR: 'ROCKET HIDEOUT ELEVATOR', + LocationIds.UNUSED_MAP_CC: 'UNUSED MAP CC', + LocationIds.UNUSED_MAP_CD: 'UNUSED MAP CD', + LocationIds.UNUSED_MAP_CE: 'UNUSED MAP CE', + LocationIds.SILPH_CO_2F: 'SILPH CO 2F', + LocationIds.SILPH_CO_3F: 'SILPH CO 3F', + LocationIds.SILPH_CO_4F: 'SILPH CO 4F', + LocationIds.SILPH_CO_5F: 'SILPH CO 5F', + LocationIds.SILPH_CO_6F: 'SILPH CO 6F', + LocationIds.SILPH_CO_7F: 'SILPH CO 7F', + LocationIds.SILPH_CO_8F: 'SILPH CO 8F', + LocationIds.POKEMON_MANSION_2F: 'POKEMON MANSION 2F', + LocationIds.POKEMON_MANSION_3F: 'POKEMON MANSION 3F', + LocationIds.POKEMON_MANSION_B1F: 'POKEMON MANSION B1F', + LocationIds.SAFARI_ZONE_EAST: 'SAFARI ZONE EAST', + LocationIds.SAFARI_ZONE_NORTH: 'SAFARI ZONE NORTH', + LocationIds.SAFARI_ZONE_WEST: 'SAFARI ZONE WEST', + LocationIds.SAFARI_ZONE_CENTER: 'SAFARI ZONE CENTER', + LocationIds.SAFARI_ZONE_CENTER_REST_HOUSE: 'SAFARI ZONE CENTER REST HOUSE', + LocationIds.SAFARI_ZONE_SECRET_HOUSE: 'SAFARI ZONE SECRET HOUSE', + LocationIds.SAFARI_ZONE_WEST_REST_HOUSE: 'SAFARI ZONE WEST REST HOUSE', + LocationIds.SAFARI_ZONE_EAST_REST_HOUSE: 'SAFARI ZONE EAST REST HOUSE', + LocationIds.SAFARI_ZONE_NORTH_REST_HOUSE: 'SAFARI ZONE NORTH REST HOUSE', + LocationIds.CERULEAN_CAVE_2F: 'CERULEAN CAVE 2F', + LocationIds.CERULEAN_CAVE_B1F: 'CERULEAN CAVE B1F', + LocationIds.CERULEAN_CAVE_1F: 'CERULEAN CAVE 1F', + LocationIds.NAME_RATERS_HOUSE: 'NAME RATER\'S HOUSE', + LocationIds.CERULEAN_BADGE_HOUSE: 'CERULEAN BADGE HOUSE', + LocationIds.UNUSED_MAP_E7: 'UNUSED MAP E7', + LocationIds.ROCK_TUNNEL_B1F: 'ROCK TUNNEL B1F', + LocationIds.SILPH_CO_9F: 'SILPH CO 9F', + LocationIds.SILPH_CO_10F: 'SILPH CO 10F', + LocationIds.SILPH_CO_11F: 'SILPH CO 11F', + LocationIds.SILPH_CO_ELEVATOR: 'SILPH CO ELEVATOR', + LocationIds.UNUSED_MAP_ED: 'UNUSED MAP ED', + LocationIds.UNUSED_MAP_EE: 'UNUSED MAP EE', + LocationIds.TRADE_CENTER: 'TRADE CENTER', + LocationIds.COLOSSEUM: 'COLOSSEUM', + LocationIds.UNUSED_MAP_F1: 'UNUSED MAP F1', + LocationIds.UNUSED_MAP_F2: 'UNUSED MAP F2', + LocationIds.UNUSED_MAP_F3: 'UNUSED MAP F3', + LocationIds.UNUSED_MAP_F4: 'UNUSED MAP F4', + LocationIds.LORELEIS_ROOM: 'LORELEI\'S ROOM', + LocationIds.BRUNOS_ROOM: 'BRUNO\'S ROOM', + LocationIds.AGATHAS_ROOM: 'AGATHA\'S ROOM', } \ No newline at end of file From bd36dbdf989ae40c660e35dc4a8c79cd5348cd1c Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Mon, 6 Nov 2023 14:35:17 -0500 Subject: [PATCH 29/74] Add Move class (currently just a wrapper with static methods) --- .../game_wrapper_pokemon_gen1/core/move.py | 15 ++ .../data/moves/constants.py | 167 ++++++++++++++++++ 2 files changed, 182 insertions(+) create mode 100644 pyboy/plugins/game_wrapper_pokemon_gen1/core/move.py create mode 100644 pyboy/plugins/game_wrapper_pokemon_gen1/data/moves/constants.py diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/move.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/move.py new file mode 100644 index 000000000..e8cf82184 --- /dev/null +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/move.py @@ -0,0 +1,15 @@ +from ..data.moves.constants import MoveIds + +class Move(): + + def __init__(self, move_id): + pass + + # We can cheat with just using the enum name as the move name + # since there is no move that has any special characters in it + @staticmethod + def get_name_from_id(move_id, camel_case=False): + move_name = MoveIds(move_id).name.replace('_', ' ') + if camel_case: + return move_name.title() + return move_name \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/moves/constants.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/moves/constants.py new file mode 100644 index 000000000..da7860ad9 --- /dev/null +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/moves/constants.py @@ -0,0 +1,167 @@ +from enum import Enum + +class MoveIds(Enum): + POUND = 0x01 + KARATE_CHOP = 0x02 + DOUBLESLAP = 0x03 + COMET_PUNCH = 0x04 + MEGA_PUNCH = 0x05 + PAY_DAY = 0x06 + FIRE_PUNCH = 0x07 + ICE_PUNCH = 0x08 + THUNDERPUNCH = 0x09 + SCRATCH = 0x0a + VICEGRIP = 0x0b + GUILLOTINE = 0x0c + RAZOR_WIND = 0x0d + SWORDS_DANCE = 0x0e + CUT = 0x0f + GUST = 0x10 + WING_ATTACK = 0x11 + WHIRLWIND = 0x12 + FLY = 0x13 + BIND = 0x14 + SLAM = 0x15 + VINE_WHIP = 0x16 + STOMP = 0x17 + DOUBLE_KICK = 0x18 + MEGA_KICK = 0x19 + JUMP_KICK = 0x1a + ROLLING_KICK = 0x1b + SAND_ATTACK = 0x1c + HEADBUTT = 0x1d + HORN_ATTACK = 0x1e + FURY_ATTACK = 0x1f + HORN_DRILL = 0x20 + TACKLE = 0x21 + BODY_SLAM = 0x22 + WRAP = 0x23 + TAKE_DOWN = 0x24 + THRASH = 0x25 + DOUBLE_EDGE = 0x26 + TAIL_WHIP = 0x27 + POISON_STING = 0x28 + TWINEEDLE = 0x29 + PIN_MISSILE = 0x2a + LEER = 0x2b + BITE = 0x2c + GROWL = 0x2d + ROAR = 0x2e + SING = 0x2f + SUPERSONIC = 0x30 + SONICBOOM = 0x31 + DISABLE = 0x32 + ACID = 0x33 + EMBER = 0x34 + FLAMETHROWER = 0x35 + MIST = 0x36 + WATER_GUN = 0x37 + HYDRO_PUMP = 0x38 + SURF = 0x39 + ICE_BEAM = 0x3a + BLIZZARD = 0x3b + PSYBEAM = 0x3c + BUBBLEBEAM = 0x3d + AURORA_BEAM = 0x3e + HYPER_BEAM = 0x3f + PECK = 0x40 + DRILL_PECK = 0x41 + SUBMISSION = 0x42 + LOW_KICK = 0x43 + COUNTER = 0x44 + SEISMIC_TOSS = 0x45 + STRENGTH = 0x46 + ABSORB = 0x47 + MEGA_DRAIN = 0x48 + LEECH_SEED = 0x49 + GROWTH = 0x4a + RAZOR_LEAF = 0x4b + SOLARBEAM = 0x4c + POISONPOWDER = 0x4d + STUN_SPORE = 0x4e + SLEEP_POWDER = 0x4f + PETAL_DANCE = 0x50 + STRING_SHOT = 0x51 + DRAGON_RAGE = 0x52 + FIRE_SPIN = 0x53 + THUNDERSHOCK = 0x54 + THUNDERBOLT = 0x55 + THUNDER_WAVE = 0x56 + THUNDER = 0x57 + ROCK_THROW = 0x58 + EARTHQUAKE = 0x59 + FISSURE = 0x5a + DIG = 0x5b + TOXIC = 0x5c + CONFUSION = 0x5d + PSYCHIC_M = 0x5e + HYPNOSIS = 0x5f + MEDITATE = 0x60 + AGILITY = 0x61 + QUICK_ATTACK = 0x62 + RAGE = 0x63 + TELEPORT = 0x64 + NIGHT_SHADE = 0x65 + MIMIC = 0x66 + SCREECH = 0x67 + DOUBLE_TEAM = 0x68 + RECOVER = 0x69 + HARDEN = 0x6a + MINIMIZE = 0x6b + SMOKESCREEN = 0x6c + CONFUSE_RAY = 0x6d + WITHDRAW = 0x6e + DEFENSE_CURL = 0x6f + BARRIER = 0x70 + LIGHT_SCREEN = 0x71 + HAZE = 0x72 + REFLECT = 0x73 + FOCUS_ENERGY = 0x74 + BIDE = 0x75 + METRONOME = 0x76 + MIRROR_MOVE = 0x77 + SELFDESTRUCT = 0x78 + EGG_BOMB = 0x79 + LICK = 0x7a + SMOG = 0x7b + SLUDGE = 0x7c + BONE_CLUB = 0x7d + FIRE_BLAST = 0x7e + WATERFALL = 0x7f + CLAMP = 0x80 + SWIFT = 0x81 + SKULL_BASH = 0x82 + SPIKE_CANNON = 0x83 + CONSTRICT = 0x84 + AMNESIA = 0x85 + KINESIS = 0x86 + SOFTBOILED = 0x87 + HI_JUMP_KICK = 0x88 + GLARE = 0x89 + DREAM_EATER = 0x8a + POISON_GAS = 0x8b + BARRAGE = 0x8c + LEECH_LIFE = 0x8d + LOVELY_KISS = 0x8e + SKY_ATTACK = 0x8f + TRANSFORM = 0x90 + BUBBLE = 0x91 + DIZZY_PUNCH = 0x92 + SPORE = 0x93 + FLASH = 0x94 + PSYWAVE = 0x95 + SPLASH = 0x96 + ACID_ARMOR = 0x97 + CRABHAMMER = 0x98 + EXPLOSION = 0x99 + FURY_SWIPES = 0x9a + BONEMERANG = 0x9b + REST = 0x9c + ROCK_SLIDE = 0x9d + HYPER_FANG = 0x9e + SHARPEN = 0x9f + CONVERSION = 0xa0 + TRI_ATTACK = 0xa1 + SUPER_FANG = 0xa2 + SLASH = 0xa3 + SUBSTITUTE = 0xa4 \ No newline at end of file From 2a22a1667cb6d429b12d440c6fe5e7db1c06b476 Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Mon, 6 Nov 2023 14:54:07 -0500 Subject: [PATCH 30/74] Restructure data folder Changed data folder structure from data//constants.py and memory.py to data/constants and data/memory_addrs with files of each data type as necessary. Done bcause many data types (statuses/types/etc.) are small and don't have memory mappings in the way larger structures like Pokemon do, and making an entire directory with a single .py file containing < 20 lines felt silly. --- .../game_wrapper_pokemon_gen1/core/pokemon.py | 24 +++++++++++++------ .../constants.py => constants/locations.py} | 0 .../constants.py => constants/moves.py} | 0 .../constants.py => constants/pokemon.py} | 0 .../memory.py => memory_addrs/pokemon.py} | 0 pyboy/pyboy.py | 13 ---------- 6 files changed, 17 insertions(+), 20 deletions(-) rename pyboy/plugins/game_wrapper_pokemon_gen1/data/{locations/constants.py => constants/locations.py} (100%) rename pyboy/plugins/game_wrapper_pokemon_gen1/data/{moves/constants.py => constants/moves.py} (100%) rename pyboy/plugins/game_wrapper_pokemon_gen1/data/{pokemon/constants.py => constants/pokemon.py} (100%) rename pyboy/plugins/game_wrapper_pokemon_gen1/data/{pokemon/memory.py => memory_addrs/pokemon.py} (100%) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py index 17fba3d8c..182323cc8 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py @@ -1,5 +1,6 @@ -from ..data.pokemon.memory import PokemonBaseAddrs, PokemonOffsets -from ..data.pokemon.constants import PokemonIds, _POKEMON_NAMES, _POKEMON_POKEDEX_INDEX +from ..data.memory_addrs.pokemon import PokemonBaseAddrs, PokemonOffsets +from ..data.constants.pokemon import PokemonIds, _POKEMON_NAMES, _POKEMON_POKEDEX_INDEX +from .move import Move class Pokemon: @@ -96,13 +97,22 @@ def load_pokemon_from_party(cls, pyboy, party_location): def _generate_move_str(self): s = f"Moves:\n" + \ - f"\tMove 1: {self.move_1}\n" + \ - f"\tMove 2: {self.move_2}\n" + \ - f"\tMove 3: {self.move_3}\n" + \ - f"\tMove 4: {self.move_4}\n" + f"\t{Move.get_name_from_id(self.move_1)} ({self.pp_move_1}/)\n" + \ + f"\t{Move.get_name_from_id(self.move_2)} ({self.pp_move_2}/)\n" + \ + f"\t{Move.get_name_from_id(self.move_3)} ({self.pp_move_3}/)\n" + \ + f"\t{Move.get_name_from_id(self.move_4)} ({self.pp_move_4}/)\n" return s + + def _generate_stat_str(self): + + s = f"Stats:\n" + \ + f"\tHP: {self.max_hp}\n" + \ + f"\tAttack: {self.attack}\n" + \ + f"\tDefense: {self.defense}\n" + \ + f"\tSpeed: {self.speed}\n" + \ + f"\tSpecial: {self.special}\n" def pretty_stringify(self): - s = f"{self.name}\n" + self._generate_move_str() + s = f"{self.name}\n" + self._generate_stats_str() + self._generate_move_str() return s \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/locations/constants.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/locations.py similarity index 100% rename from pyboy/plugins/game_wrapper_pokemon_gen1/data/locations/constants.py rename to pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/locations.py diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/moves/constants.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/moves.py similarity index 100% rename from pyboy/plugins/game_wrapper_pokemon_gen1/data/moves/constants.py rename to pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/moves.py diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/pokemon/constants.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/pokemon.py similarity index 100% rename from pyboy/plugins/game_wrapper_pokemon_gen1/data/pokemon/constants.py rename to pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/pokemon.py diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/pokemon/memory.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/pokemon.py similarity index 100% rename from pyboy/plugins/game_wrapper_pokemon_gen1/data/pokemon/memory.py rename to pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/pokemon.py diff --git a/pyboy/pyboy.py b/pyboy/pyboy.py index 0ebca532c..971a1531f 100644 --- a/pyboy/pyboy.py +++ b/pyboy/pyboy.py @@ -309,19 +309,6 @@ def game_wrapper(self): A game-specific wrapper object. """ return self.plugin_manager.gamewrapper() - - def get_memory_value(self, addr): - """ - Reads a given memory address of the Game Boy's current memory state. This will not directly give you access to - all switchable memory banks. Open an issue on GitHub if that is needed, or use `PyBoy.set_memory_value` to send - MBC commands to the virtual cartridge. - - Returns - ------- - int: - An integer with the value of the memory address - """ - return self.mb.getitem(addr) def get_memory_value(self, addr, num_bytes=1, byte_order='big'): """ From 5a7fec8c340031c916071c3aa6c1fa3dba07f382 Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Mon, 6 Nov 2023 14:58:42 -0500 Subject: [PATCH 31/74] Change storage of moves in Pokemon class to list Instead of storing move_1 through move_2 as individual instance variables in the Pokemon class, we not store them in a list of size 4 as self.moves. Each individual move is still accessible as move_n through the use of property functions, but now the list of moves can be iterated over, which makes it easier to manage cases where a Pokemon has less than 4 moves without having to manually check four distinct fields --- .../game_wrapper_pokemon_gen1/core/pokemon.py | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py index 182323cc8..c96d1fde4 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py @@ -40,10 +40,7 @@ def __init__(self, self.type_1 = type_1 self.type_2 = type_2 self.catch_rate = catch_rate - self.move_1 = move_1 - self.move_2 = move_2 - self.move_3 = move_3 - self.move_4 = move_4 + self.moves = [move_1, move_2, move_3, move_4] self.trainer_id = trainer_id self.experience = experience self.hp_ev = hp_ev @@ -68,6 +65,22 @@ def __init__(self, def name(self): return Pokemon.get_pokemon_name_from_id(self.pokemon_id) + @property + def move_1(self): + return self.moves[0] + + @property + def move_2(self): + return self.moves[1] + + @property + def move_3(self): + return self.moves[2] + + @property + def move_4(self): + return self.moves[3] + @staticmethod def get_pokemon_name_from_id(pokemon_id): return _POKEMON_NAMES.get(PokemonIds(pokemon_id)) From c1ccbc4a2547b3535ca3e264a0ac80ad39838995 Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Mon, 6 Nov 2023 15:14:23 -0500 Subject: [PATCH 32/74] Add defaults tring to fill in nonexistent move slots in pretty printing --- pyboy/plugins/game_wrapper_pokemon_gen1/core/move.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/move.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/move.py index e8cf82184..27c90b687 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/move.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/move.py @@ -1,14 +1,18 @@ -from ..data.moves.constants import MoveIds +from ..data.constants.moves import MoveIds class Move(): + NONEXISTENT_MOVE_STR = "---" + def __init__(self, move_id): pass # We can cheat with just using the enum name as the move name # since there is no move that has any special characters in it - @staticmethod - def get_name_from_id(move_id, camel_case=False): + @classmethod + def get_name_from_id(cls, move_id, camel_case=False): + if move_id == 0: + return cls.NONEXISTENT_MOVE_STR move_name = MoveIds(move_id).name.replace('_', ' ') if camel_case: return move_name.title() From 1bb770e0b10813914eb7c05ab14bad91d897ccb5 Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Mon, 6 Nov 2023 15:15:23 -0500 Subject: [PATCH 33/74] Restructure stats, evs, and move PP to also be stored in lists in the Pokemon class --- .../game_wrapper_pokemon_gen1/core/pokemon.py | 84 ++++++++++++++----- 1 file changed, 65 insertions(+), 19 deletions(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py index c96d1fde4..8f39150a7 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py @@ -43,23 +43,14 @@ def __init__(self, self.moves = [move_1, move_2, move_3, move_4] self.trainer_id = trainer_id self.experience = experience - self.hp_ev = hp_ev - self.attack_ev = attack_ev - self.defense_ev = defense_ev - self.speed_ev = speed_ev - self.special_ev = special_ev + # EV order: HP, Attack, Defense, Speed, Special + self.evs = [hp_ev, attack_ev, defense_ev, speed_ev, special_ev] self.attack_defense_iv = attack_defense_iv self.speed_special_iv = speed_special_iv - self.pp_move_1 = pp_move_1 - self.pp_move_2 = pp_move_2 - self.pp_move_3 = pp_move_3 - self.pp_move_4 = pp_move_4 + self.pp_moves = [pp_move_1, pp_move_2, pp_move_3, pp_move_4] self.level = level - self.max_hp = max_hp - self.attack = attack - self.defense = defense - self.speed = speed - self.special = special + # Stat order same as EV order + self.stats = [max_hp, attack, defense, speed, special] @property def name(self): @@ -81,6 +72,62 @@ def move_3(self): def move_4(self): return self.moves[3] + @property + def pp_move_1(self): + return self.pp_moves[0] + + @property + def pp_move_2(self): + return self.pp_moves[1] + + @property + def pp_move_3(self): + return self.pp_moves[2] + + @property + def pp_move_4(self): + return self.pp_moves[3] + + @property + def hp_ev(self): + return self.evs[0] + + @property + def attack_ev(self): + return self.evs[1] + + @property + def defense_ev(self): + return self.evs[2] + + @property + def speed_ev(self): + return self.evs[3] + + @property + def special_ev(self): + return self.evs[4] + + @property + def max_hp(self): + return self.stats[0] + + @property + def attack(self): + return self.stats[1] + + @property + def defense(self): + return self.stats[2] + + @property + def speed(self): + return self.stats[3] + + @property + def special(self): + return self.stats[4] + @staticmethod def get_pokemon_name_from_id(pokemon_id): return _POKEMON_NAMES.get(PokemonIds(pokemon_id)) @@ -109,11 +156,10 @@ def load_pokemon_from_party(cls, pyboy, party_location): return cls._load_pokemon_from_address(pyboy, pokemon_base_address) def _generate_move_str(self): - s = f"Moves:\n" + \ - f"\t{Move.get_name_from_id(self.move_1)} ({self.pp_move_1}/)\n" + \ - f"\t{Move.get_name_from_id(self.move_2)} ({self.pp_move_2}/)\n" + \ - f"\t{Move.get_name_from_id(self.move_3)} ({self.pp_move_3}/)\n" + \ - f"\t{Move.get_name_from_id(self.move_4)} ({self.pp_move_4}/)\n" + s = f"Moves:\n" + + for i, move_id in enumerate(self.moves): + s += f"\t{Move.get_name_from_id(move_id)} ({self.pp_moves[i]}/)\n" return s From 902c9f4db45cbad2cb6ae479f66aff8a4194b293 Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Mon, 6 Nov 2023 15:29:16 -0500 Subject: [PATCH 34/74] Finish splitting constants into respective files --- .../game_wrapper_pokemon_gen1/constants.py | 405 ------------------ .../game_wrapper_pokemon_gen1/core/pokemon.py | 3 +- .../data/constants/items.py | 155 +++++++ .../data/constants/sprites.py | 75 ++++ .../data/constants/status.py | 8 + .../game_wrapper_pokemon_gen1.py | 46 +- .../game_wrapper_pokemon_gen1/utils.py | 3 +- 7 files changed, 262 insertions(+), 433 deletions(-) delete mode 100644 pyboy/plugins/game_wrapper_pokemon_gen1/constants.py create mode 100644 pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/items.py create mode 100644 pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/sprites.py create mode 100644 pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/status.py diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py b/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py deleted file mode 100644 index af5e2f188..000000000 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/constants.py +++ /dev/null @@ -1,405 +0,0 @@ -from enum import Enum - -STRING_TERMINATOR = 80 -ASCII_DELTA = 63 - -class Moves(Enum): - POUND = 0x01 - KARATE_CHOP = 0x02 - DOUBLESLAP = 0x03 - COMET_PUNCH = 0x04 - MEGA_PUNCH = 0x05 - PAY_DAY = 0x06 - FIRE_PUNCH = 0x07 - ICE_PUNCH = 0x08 - THUNDERPUNCH = 0x09 - SCRATCH = 0x0a - VICEGRIP = 0x0b - GUILLOTINE = 0x0c - RAZOR_WIND = 0x0d - SWORDS_DANCE = 0x0e - CUT = 0x0f - GUST = 0x10 - WING_ATTACK = 0x11 - WHIRLWIND = 0x12 - FLY = 0x13 - BIND = 0x14 - SLAM = 0x15 - VINE_WHIP = 0x16 - STOMP = 0x17 - DOUBLE_KICK = 0x18 - MEGA_KICK = 0x19 - JUMP_KICK = 0x1a - ROLLING_KICK = 0x1b - SAND_ATTACK = 0x1c - HEADBUTT = 0x1d - HORN_ATTACK = 0x1e - FURY_ATTACK = 0x1f - HORN_DRILL = 0x20 - TACKLE = 0x21 - BODY_SLAM = 0x22 - WRAP = 0x23 - TAKE_DOWN = 0x24 - THRASH = 0x25 - DOUBLE_EDGE = 0x26 - TAIL_WHIP = 0x27 - POISON_STING = 0x28 - TWINEEDLE = 0x29 - PIN_MISSILE = 0x2a - LEER = 0x2b - BITE = 0x2c - GROWL = 0x2d - ROAR = 0x2e - SING = 0x2f - SUPERSONIC = 0x30 - SONICBOOM = 0x31 - DISABLE = 0x32 - ACID = 0x33 - EMBER = 0x34 - FLAMETHROWER = 0x35 - MIST = 0x36 - WATER_GUN = 0x37 - HYDRO_PUMP = 0x38 - SURF = 0x39 - ICE_BEAM = 0x3a - BLIZZARD = 0x3b - PSYBEAM = 0x3c - BUBBLEBEAM = 0x3d - AURORA_BEAM = 0x3e - HYPER_BEAM = 0x3f - PECK = 0x40 - DRILL_PECK = 0x41 - SUBMISSION = 0x42 - LOW_KICK = 0x43 - COUNTER = 0x44 - SEISMIC_TOSS = 0x45 - STRENGTH = 0x46 - ABSORB = 0x47 - MEGA_DRAIN = 0x48 - LEECH_SEED = 0x49 - GROWTH = 0x4a - RAZOR_LEAF = 0x4b - SOLARBEAM = 0x4c - POISONPOWDER = 0x4d - STUN_SPORE = 0x4e - SLEEP_POWDER = 0x4f - PETAL_DANCE = 0x50 - STRING_SHOT = 0x51 - DRAGON_RAGE = 0x52 - FIRE_SPIN = 0x53 - THUNDERSHOCK = 0x54 - THUNDERBOLT = 0x55 - THUNDER_WAVE = 0x56 - THUNDER = 0x57 - ROCK_THROW = 0x58 - EARTHQUAKE = 0x59 - FISSURE = 0x5a - DIG = 0x5b - TOXIC = 0x5c - CONFUSION = 0x5d - PSYCHIC_M = 0x5e - HYPNOSIS = 0x5f - MEDITATE = 0x60 - AGILITY = 0x61 - QUICK_ATTACK = 0x62 - RAGE = 0x63 - TELEPORT = 0x64 - NIGHT_SHADE = 0x65 - MIMIC = 0x66 - SCREECH = 0x67 - DOUBLE_TEAM = 0x68 - RECOVER = 0x69 - HARDEN = 0x6a - MINIMIZE = 0x6b - SMOKESCREEN = 0x6c - CONFUSE_RAY = 0x6d - WITHDRAW = 0x6e - DEFENSE_CURL = 0x6f - BARRIER = 0x70 - LIGHT_SCREEN = 0x71 - HAZE = 0x72 - REFLECT = 0x73 - FOCUS_ENERGY = 0x74 - BIDE = 0x75 - METRONOME = 0x76 - MIRROR_MOVE = 0x77 - SELFDESTRUCT = 0x78 - EGG_BOMB = 0x79 - LICK = 0x7a - SMOG = 0x7b - SLUDGE = 0x7c - BONE_CLUB = 0x7d - FIRE_BLAST = 0x7e - WATERFALL = 0x7f - CLAMP = 0x80 - SWIFT = 0x81 - SKULL_BASH = 0x82 - SPIKE_CANNON = 0x83 - CONSTRICT = 0x84 - AMNESIA = 0x85 - KINESIS = 0x86 - SOFTBOILED = 0x87 - HI_JUMP_KICK = 0x88 - GLARE = 0x89 - DREAM_EATER = 0x8a - POISON_GAS = 0x8b - BARRAGE = 0x8c - LEECH_LIFE = 0x8d - LOVELY_KISS = 0x8e - SKY_ATTACK = 0x8f - TRANSFORM = 0x90 - BUBBLE = 0x91 - DIZZY_PUNCH = 0x92 - SPORE = 0x93 - FLASH = 0x94 - PSYWAVE = 0x95 - SPLASH = 0x96 - ACID_ARMOR = 0x97 - CRABHAMMER = 0x98 - EXPLOSION = 0x99 - FURY_SWIPES = 0x9a - BONEMERANG = 0x9b - REST = 0x9c - ROCK_SLIDE = 0x9d - HYPER_FANG = 0x9e - SHARPEN = 0x9f - CONVERSION = 0xa0 - TRI_ATTACK = 0xa1 - SUPER_FANG = 0xa2 - SLASH = 0xa3 - SUBSTITUTE = 0xa4 - -class Items(Enum): - MASTER_BALL = 0x01 - ULTRA_BALL = 0x02 - GREAT_BALL = 0x03 - POKE_BALL = 0x04 - TOWN_MAP = 0x05 - BICYCLE = 0x06 - SURFBOARD = 0x07 - SAFARI_BALL = 0x08 - POKEDEX = 0x09 - MOON_STONE = 0x0A - ANTIDOTE = 0x0B - BURN_HEAL = 0x0C - ICE_HEAL = 0x0D - AWAKENING = 0x0E - PARLYZ_HEAL = 0x0F - FULL_RESTORE = 0x10 - MAX_POTION = 0x11 - HYPER_POTION = 0x12 - SUPER_POTION = 0x13 - POTION = 0x14 - BOULDERBADGE = 0x15 - CASCADEBADGE = 0x16 - THUNDERBADGE = 0x17 - RAINBOWBADGE = 0x18 - SOULBADGE = 0x19 - MARSHBADGE = 0x1A - VOLCANOBADGE = 0x1B - EARTHBADGE = 0x1C - ESCAPE_ROPE = 0x1D - REPEL = 0x1E - OLD_AMBER = 0x1F - FIRE_STONE = 0x20 - THUNDER_STONE = 0x21 - WATER_STONE = 0x22 - HP_UP = 0x23 - PROTEIN = 0x24 - IRON = 0x25 - CARBOS = 0x26 - CALCIUM = 0x27 - RARE_CANDY = 0x28 - DOME_FOSSIL = 0x29 - HELIX_FOSSIL = 0x2A - SECRET_KEY = 0x2B - UNUSED_ITEM = 0x2C - BIKE_VOUCHER = 0x2D - X_ACCURACY = 0x2E - LEAF_STONE = 0x2F - CARD_KEY = 0x30 - NUGGET = 0x31 - PP_UP_2 = 0x32 - POKE_DOLL = 0x33 - FULL_HEAL = 0x34 - REVIVE = 0x35 - MAX_REVIVE = 0x36 - GUARD_SPEC = 0x37 - SUPER_REPEL = 0x38 - MAX_REPEL = 0x39 - DIRE_HIT = 0x3A - COIN = 0x3B - FRESH_WATER = 0x3C - SODA_POP = 0x3D - LEMONADE = 0x3E - S_S_TICKET = 0x3F - GOLD_TEETH = 0x40 - X_ATTACK = 0x41 - X_DEFEND = 0x42 - X_SPEED = 0x43 - X_SPECIAL = 0x44 - COIN_CASE = 0x45 - OAKS_PARCEL = 0x46 - ITEMFINDER = 0x47 - SILPH_SCOPE = 0x48 - POKE_FLUTE = 0x49 - LIFT_KEY = 0x4A - EXP_ALL = 0x4B - OLD_ROD = 0x4C - GOOD_ROD = 0x4D - SUPER_ROD = 0x4E - PP_UP = 0x4F - ETHER = 0x50 - MAX_ETHER = 0x51 - ELIXER = 0x52 - MAX_ELIXER = 0x53 - FLOOR_B2F = 0x54 - FLOOR_B1F = 0x55 - FLOOR_1F = 0x56 - FLOOR_2F = 0x57 - FLOOR_3F = 0x58 - FLOOR_4F = 0x59 - FLOOR_5F = 0x5A - FLOOR_6F = 0x5B - FLOOR_7F = 0x5C - FLOOR_8F = 0x5D - FLOOR_9F = 0x5E - FLOOR_10F = 0x5F - FLOOR_11F = 0x60 - FLOOR_B4F = 0x61 - HM_01 = 0xC4 - HM_02 = 0xC5 - HM_03 = 0xC6 - HM_04 = 0xC7 - HM_05 = 0xC8 - TM_01 = 0xC9 - TM_02 = 0xCA - TM_03 = 0xCB - TM_04 = 0xCC - TM_05 = 0xCD - TM_06 = 0xCE - TM_07 = 0xCF - TM_08 = 0xD0 - TM_09 = 0xD1 - TM_10 = 0xD2 - TM_11 = 0xD3 - TM_12 = 0xD4 - TM_13 = 0xD5 - TM_14 = 0xD6 - TM_15 = 0xD7 - TM_16 = 0xD8 - TM_17 = 0xD9 - TM_18 = 0xDA - TM_19 = 0xDB - TM_20 = 0xDC - TM_21 = 0xDD - TM_22 = 0xDE - TM_23 = 0xDF - TM_24 = 0xE0 - TM_25 = 0xE1 - TM_26 = 0xE2 - TM_27 = 0xE3 - TM_28 = 0xE4 - TM_29 = 0xE5 - TM_30 = 0xE6 - TM_31 = 0xE7 - TM_32 = 0xE8 - TM_33 = 0xE9 - TM_34 = 0xEA - TM_35 = 0xEB - TM_36 = 0xEC - TM_37 = 0xED - TM_38 = 0xEE - TM_39 = 0xEF - TM_40 = 0xF0 - TM_41 = 0xF1 - TM_42 = 0xF2 - TM_43 = 0xF3 - TM_44 = 0xF4 - TM_45 = 0xF5 - TM_46 = 0xF6 - TM_47 = 0xF7 - TM_48 = 0xF8 - TM_49 = 0xF9 - TM_50 = 0xFA - -class Sprites(Enum): - RED = 0x01 - BLUE = 0x02 - OAK = 0x03 - BUG_CATCHER = 0x04 - SLOWBRO = 0x05 - LASS = 0x06 - BLACK_HAIR_BOY_1 = 0x07 - LITTLE_GIRL = 0x08 - BIRD = 0x09 - FAT_BALD_GUY = 0x0a - GAMBLER = 0x0b - BLACK_HAIR_BOY_2 = 0x0c - GIRL = 0x0d - HIKER = 0x0e - FOULARD_WOMAN = 0x0f - GENTLEMAN = 0x10 - DAISY = 0x11 - BIKER = 0x12 - SAILOR = 0x13 - COOK = 0x14 - BIKE_SHOP_GUY = 0x15 - MR_FUJI = 0x16 - GIOVANNI = 0x17 - ROCKET = 0x18 - MEDIUM = 0x19 - WAITER = 0x1a - ERIKA = 0x1b - MOM_GEISHA = 0x1c - BRUNETTE_GIRL = 0x1d - LANCE = 0x1e - OAK_SCIENTIST_AIDE = 0x1f - OAK_AIDE = 0x20 - ROCKER = 0x21 - SWIMMER = 0x22 - WHITE_PLAYER = 0x23 - GYM_HELPER = 0x24 - OLD_PERSON = 0x25 - MART_GUY = 0x26 - FISHER = 0x27 - OLD_MEDIUM_WOMAN = 0x28 - NURSE = 0x29 - CABLE_CLUB_WOMAN = 0x2a - MR_MASTERBALL = 0x2b - LAPRAS_GIVER = 0x2c - WARDEN = 0x2d - SS_CAPTAIN = 0x2e - FISHER2 = 0x2f - BLACKBELT = 0x30 - GUARD = 0x31 - COP_GUARD = 0x32 - MOM = 0x33 - BALDING_GUY = 0x34 - YOUNG_BOY = 0x35 - GAMEBOY_KID = 0x36 - GAMEBOY_KID_COPY = 0x37 - CLEFAIRY = 0x38 - AGATHA = 0x39 - BRUNO = 0x3a - LORELEI = 0x3b - SEEL = 0x3c - BALL = 0x3d - OMANYTE = 0x3e - BOULDER = 0x3f - PAPER_SHEET = 0x40 - BOOK_MAP_DEX = 0x41 - CLIPBOARD = 0x42 - SNORLAX = 0x43 - OLD_AMBER_COPY = 0x44 - OLD_AMBER = 0x45 - LYING_OLD_MAN_UNUSED_1 = 0x46 - LYING_OLD_MAN_UNUSED_2 = 0x47 - LYING_OLD_MAN = 0x48 - -class Statuses(Enum): - ASLEEP = 4 - POISONED = 8 - BURNED = 16 - FROZEN = 32 - PARALYZED = 64 \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py index 8f39150a7..38de2c6a5 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py @@ -163,7 +163,7 @@ def _generate_move_str(self): return s - def _generate_stat_str(self): + def _generate_stats_str(self): s = f"Stats:\n" + \ f"\tHP: {self.max_hp}\n" + \ @@ -171,6 +171,7 @@ def _generate_stat_str(self): f"\tDefense: {self.defense}\n" + \ f"\tSpeed: {self.speed}\n" + \ f"\tSpecial: {self.special}\n" + return s def pretty_stringify(self): s = f"{self.name}\n" + self._generate_stats_str() + self._generate_move_str() diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/items.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/items.py new file mode 100644 index 000000000..e0dd897a9 --- /dev/null +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/items.py @@ -0,0 +1,155 @@ +from enum import Enum + +class Items(Enum): + MASTER_BALL = 0x01 + ULTRA_BALL = 0x02 + GREAT_BALL = 0x03 + POKE_BALL = 0x04 + TOWN_MAP = 0x05 + BICYCLE = 0x06 + SURFBOARD = 0x07 + SAFARI_BALL = 0x08 + POKEDEX = 0x09 + MOON_STONE = 0x0A + ANTIDOTE = 0x0B + BURN_HEAL = 0x0C + ICE_HEAL = 0x0D + AWAKENING = 0x0E + PARLYZ_HEAL = 0x0F + FULL_RESTORE = 0x10 + MAX_POTION = 0x11 + HYPER_POTION = 0x12 + SUPER_POTION = 0x13 + POTION = 0x14 + BOULDERBADGE = 0x15 + CASCADEBADGE = 0x16 + THUNDERBADGE = 0x17 + RAINBOWBADGE = 0x18 + SOULBADGE = 0x19 + MARSHBADGE = 0x1A + VOLCANOBADGE = 0x1B + EARTHBADGE = 0x1C + ESCAPE_ROPE = 0x1D + REPEL = 0x1E + OLD_AMBER = 0x1F + FIRE_STONE = 0x20 + THUNDER_STONE = 0x21 + WATER_STONE = 0x22 + HP_UP = 0x23 + PROTEIN = 0x24 + IRON = 0x25 + CARBOS = 0x26 + CALCIUM = 0x27 + RARE_CANDY = 0x28 + DOME_FOSSIL = 0x29 + HELIX_FOSSIL = 0x2A + SECRET_KEY = 0x2B + UNUSED_ITEM = 0x2C + BIKE_VOUCHER = 0x2D + X_ACCURACY = 0x2E + LEAF_STONE = 0x2F + CARD_KEY = 0x30 + NUGGET = 0x31 + PP_UP_2 = 0x32 + POKE_DOLL = 0x33 + FULL_HEAL = 0x34 + REVIVE = 0x35 + MAX_REVIVE = 0x36 + GUARD_SPEC = 0x37 + SUPER_REPEL = 0x38 + MAX_REPEL = 0x39 + DIRE_HIT = 0x3A + COIN = 0x3B + FRESH_WATER = 0x3C + SODA_POP = 0x3D + LEMONADE = 0x3E + S_S_TICKET = 0x3F + GOLD_TEETH = 0x40 + X_ATTACK = 0x41 + X_DEFEND = 0x42 + X_SPEED = 0x43 + X_SPECIAL = 0x44 + COIN_CASE = 0x45 + OAKS_PARCEL = 0x46 + ITEMFINDER = 0x47 + SILPH_SCOPE = 0x48 + POKE_FLUTE = 0x49 + LIFT_KEY = 0x4A + EXP_ALL = 0x4B + OLD_ROD = 0x4C + GOOD_ROD = 0x4D + SUPER_ROD = 0x4E + PP_UP = 0x4F + ETHER = 0x50 + MAX_ETHER = 0x51 + ELIXER = 0x52 + MAX_ELIXER = 0x53 + FLOOR_B2F = 0x54 + FLOOR_B1F = 0x55 + FLOOR_1F = 0x56 + FLOOR_2F = 0x57 + FLOOR_3F = 0x58 + FLOOR_4F = 0x59 + FLOOR_5F = 0x5A + FLOOR_6F = 0x5B + FLOOR_7F = 0x5C + FLOOR_8F = 0x5D + FLOOR_9F = 0x5E + FLOOR_10F = 0x5F + FLOOR_11F = 0x60 + FLOOR_B4F = 0x61 + HM_01 = 0xC4 + HM_02 = 0xC5 + HM_03 = 0xC6 + HM_04 = 0xC7 + HM_05 = 0xC8 + TM_01 = 0xC9 + TM_02 = 0xCA + TM_03 = 0xCB + TM_04 = 0xCC + TM_05 = 0xCD + TM_06 = 0xCE + TM_07 = 0xCF + TM_08 = 0xD0 + TM_09 = 0xD1 + TM_10 = 0xD2 + TM_11 = 0xD3 + TM_12 = 0xD4 + TM_13 = 0xD5 + TM_14 = 0xD6 + TM_15 = 0xD7 + TM_16 = 0xD8 + TM_17 = 0xD9 + TM_18 = 0xDA + TM_19 = 0xDB + TM_20 = 0xDC + TM_21 = 0xDD + TM_22 = 0xDE + TM_23 = 0xDF + TM_24 = 0xE0 + TM_25 = 0xE1 + TM_26 = 0xE2 + TM_27 = 0xE3 + TM_28 = 0xE4 + TM_29 = 0xE5 + TM_30 = 0xE6 + TM_31 = 0xE7 + TM_32 = 0xE8 + TM_33 = 0xE9 + TM_34 = 0xEA + TM_35 = 0xEB + TM_36 = 0xEC + TM_37 = 0xED + TM_38 = 0xEE + TM_39 = 0xEF + TM_40 = 0xF0 + TM_41 = 0xF1 + TM_42 = 0xF2 + TM_43 = 0xF3 + TM_44 = 0xF4 + TM_45 = 0xF5 + TM_46 = 0xF6 + TM_47 = 0xF7 + TM_48 = 0xF8 + TM_49 = 0xF9 + TM_50 = 0xFA \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/sprites.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/sprites.py new file mode 100644 index 000000000..7fa3c1bf7 --- /dev/null +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/sprites.py @@ -0,0 +1,75 @@ +from enum import Enum + +class Sprites(Enum): + RED = 0x01 + BLUE = 0x02 + OAK = 0x03 + BUG_CATCHER = 0x04 + SLOWBRO = 0x05 + LASS = 0x06 + BLACK_HAIR_BOY_1 = 0x07 + LITTLE_GIRL = 0x08 + BIRD = 0x09 + FAT_BALD_GUY = 0x0a + GAMBLER = 0x0b + BLACK_HAIR_BOY_2 = 0x0c + GIRL = 0x0d + HIKER = 0x0e + FOULARD_WOMAN = 0x0f + GENTLEMAN = 0x10 + DAISY = 0x11 + BIKER = 0x12 + SAILOR = 0x13 + COOK = 0x14 + BIKE_SHOP_GUY = 0x15 + MR_FUJI = 0x16 + GIOVANNI = 0x17 + ROCKET = 0x18 + MEDIUM = 0x19 + WAITER = 0x1a + ERIKA = 0x1b + MOM_GEISHA = 0x1c + BRUNETTE_GIRL = 0x1d + LANCE = 0x1e + OAK_SCIENTIST_AIDE = 0x1f + OAK_AIDE = 0x20 + ROCKER = 0x21 + SWIMMER = 0x22 + WHITE_PLAYER = 0x23 + GYM_HELPER = 0x24 + OLD_PERSON = 0x25 + MART_GUY = 0x26 + FISHER = 0x27 + OLD_MEDIUM_WOMAN = 0x28 + NURSE = 0x29 + CABLE_CLUB_WOMAN = 0x2a + MR_MASTERBALL = 0x2b + LAPRAS_GIVER = 0x2c + WARDEN = 0x2d + SS_CAPTAIN = 0x2e + FISHER2 = 0x2f + BLACKBELT = 0x30 + GUARD = 0x31 + COP_GUARD = 0x32 + MOM = 0x33 + BALDING_GUY = 0x34 + YOUNG_BOY = 0x35 + GAMEBOY_KID = 0x36 + GAMEBOY_KID_COPY = 0x37 + CLEFAIRY = 0x38 + AGATHA = 0x39 + BRUNO = 0x3a + LORELEI = 0x3b + SEEL = 0x3c + BALL = 0x3d + OMANYTE = 0x3e + BOULDER = 0x3f + PAPER_SHEET = 0x40 + BOOK_MAP_DEX = 0x41 + CLIPBOARD = 0x42 + SNORLAX = 0x43 + OLD_AMBER_COPY = 0x44 + OLD_AMBER = 0x45 + LYING_OLD_MAN_UNUSED_1 = 0x46 + LYING_OLD_MAN_UNUSED_2 = 0x47 + LYING_OLD_MAN = 0x48 \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/status.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/status.py new file mode 100644 index 000000000..3d5e005d8 --- /dev/null +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/status.py @@ -0,0 +1,8 @@ +from enum import Enum + +class Statuses(Enum): + ASLEEP = 4 + POISONED = 8 + BURNED = 16 + FROZEN = 32 + PARALYZED = 64 \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py index a17e5099a..c54672bb9 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py @@ -13,8 +13,8 @@ from pyboy.logger import logger from ..base_plugin import PyBoyGameWrapper from .core.gen_1_memory_manager import Gen1MemoryManager -from . import constants -from .utils import get_character_index +from .utils import get_character_index, STRING_TERMINATOR, ASCII_DELTA +from data.constants.status import Statuses PKMN_SIZE = 0x2C BYTE_ORDER = 'big' @@ -123,7 +123,7 @@ def set_text(self, text, address): i += 1 except: pass - self.pyboy.set_memory_value(address + i, constants.STRING_TERMINATOR) + self.pyboy.set_memory_value(address + i, STRING_TERMINATOR) def set_rom_text(self, text, bank, address): i = 0 @@ -177,10 +177,10 @@ def get_text(self, address, cap = 16): while i < cap: value = self.pyboy.get_memory_value(address + i) try: - text += chr(value - constants.ASCII_DELTA) + text += chr(value - ASCII_DELTA) except: pass - if value == constants.STRING_TERMINATOR: + if value == STRING_TERMINATOR: break i += 1 return text @@ -192,19 +192,19 @@ def get_pokemon(self, party_index): return self.memory_manager.load_pokemon_from_party(party_index) def set_player_monster_asleep(self, index): - self.set_player_monster_status(index, constants.STATUS_ASLEEP) + self.set_player_monster_status(index, Statuses.ASLEEP) def set_player_monster_poisoned(self, index): - self.set_player_monster_status(index, constants.STATUS_POISONED) + self.set_player_monster_status(index, Statuses.POISONED) def set_player_monster_burned(self, index): - self.set_player_monster_status(index, constants.STATUS_BURNED) + self.set_player_monster_status(index, Statuses.BURNED) def set_player_monster_frozen(self, index): - self.set_player_monster_status(index, constants.STATUS_FROZEN) + self.set_player_monster_status(index, Statuses.FROZEN) def set_player_monster_paralyzed(self, index): - self.set_player_monster_status(index, constants.STATUS_PARALYZED) + self.set_player_monster_status(index, Statuses.PARALYZED) def set_player_monster_no_ailment(self, index): self.set_player_monster_status(index, 0) @@ -216,19 +216,19 @@ def set_active_player_monster_status(self, status): self.pyboy.set_memory_value(0xD018, status) def set_active_player_monster_asleep(self): - self.set_active_player_monster_status(constants.STATUS_ASLEEP) + self.set_active_player_monster_status(Statuses.ASLEEP) def set_active_player_monster_poisoned(self): - self.set_active_player_monster_status(constants.STATUS_POISONED) + self.set_active_player_monster_status(Statuses.POISONED) def set_active_player_monster_burned(self): - self.set_active_player_monster_status(constants.STATUS_BURNED) + self.set_active_player_monster_status(Statuses.BURNED) def set_active_player_monster_frozen(self): - self.set_active_player_monster_status(constants.STATUS_FROZEN) + self.set_active_player_monster_status(Statuses.FROZEN) def set_active_player_monster_paralyzed(self): - self.set_active_player_monster_status(constants.STATUS_PARALYZED) + self.set_active_player_monster_status(Statuses.PARALYZED) def set_active_player_monster_no_ailment(self): self.set_active_player_monster_status(0) @@ -249,19 +249,19 @@ def set_active_opponent_monster_status(self, status): self.pyboy.set_memory_value(0xCFE9, status) def set_active_opponent_monster_asleep(self): - self.set_active_opponent_monster_status(constants.STATUS_ASLEEP) + self.set_active_opponent_monster_status(Statuses.ASLEEP) def set_active_opponent_monster_poisoned(self): - self.set_active_opponent_monster_status(constants.STATUS_POISONED) + self.set_active_opponent_monster_status(Statuses.POISONED) def set_active_opponent_monster_burned(self): - self.set_active_opponent_monster_status(constants.STATUS_BURNED) + self.set_active_opponent_monster_status(Statuses.BURNED) def set_active_opponent_monster_frozen(self): - self.set_active_opponent_monster_status(constants.STATUS_FROZEN) + self.set_active_opponent_monster_status(Statuses.FROZEN) def set_active_opponent_monster_paralyzed(self): - self.set_active_opponent_monster_status(constants.STATUS_PARALYZED) + self.set_active_opponent_monster_status(Statuses.PARALYZED) def set_active_opponent_monster_no_ailment(self): self.set_active_opponent_monster_status(0) @@ -288,10 +288,4 @@ def is_battle_happening(self): def get_current_map(self): return self.pyboy.get_memory_value(0xD35E) - def get_current_map_name(self): - return constants.MAP_NAMES[self.get_current_map()] - - def set_wild_encounter_rate(self, value): - self.pyboy.set_memory_value(0xD887, value) - # TODO: Add player position functions diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/utils.py b/pyboy/plugins/game_wrapper_pokemon_gen1/utils.py index 77d52d432..f027bd403 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/utils.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/utils.py @@ -1,4 +1,5 @@ -from .constants import ASCII_DELTA +STRING_TERMINATOR = 80 +ASCII_DELTA = 63 def get_character_index(character): if character == ' ': From b45490b968905c10ea1e6a1fca46e753ebe369db Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Tue, 7 Nov 2023 10:04:40 -0500 Subject: [PATCH 35/74] Change PokemonOffsets to PokemonMemoryOffsets to make it clearer what the enum represents --- .../game_wrapper_pokemon_gen1/data/memory_addrs/pokemon.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/pokemon.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/pokemon.py index 62adc7806..43dac970d 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/pokemon.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/pokemon.py @@ -11,7 +11,7 @@ class PokemonBaseAddrs(Enum): # Offsets for Pokemon data access # Structure is (offset, num bytes) -class PokemonOffsets(Enum): +class PokemonMemoryOffsets(Enum): ID = (0x0, 1) CURRENT_HP = (0x1, 2) STATUS = (0x3, 1) From 024407cb3b6e76f048f8ce8fd312dca982640d39 Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Tue, 7 Nov 2023 11:01:26 -0500 Subject: [PATCH 36/74] Reset pyboy.py, going to try and avoid chaning it for now --- pyboy/pyboy.py | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/pyboy/pyboy.py b/pyboy/pyboy.py index 971a1531f..40a2f597b 100644 --- a/pyboy/pyboy.py +++ b/pyboy/pyboy.py @@ -309,26 +309,23 @@ def game_wrapper(self): A game-specific wrapper object. """ return self.plugin_manager.gamewrapper() - - def get_memory_value(self, addr, num_bytes=1, byte_order='big'): + + def get_memory_value(self, addr): """ - Reads num_bytes consecutive memory addresses of the Game Boy's current memory state. This will not directly give you access to + Reads a given memory address of the Game Boy's current memory state. This will not directly give you access to all switchable memory banks. Open an issue on GitHub if that is needed, or use `PyBoy.set_memory_value` to send MBC commands to the virtual cartridge. Returns ------- int: - An integer with the value of the memory addresses in byte_order endian format + An integer with the value of the memory address """ - bytes = [] - for i in range(num_bytes): - bytes.append(self.mb.getitem(addr + i)) - return int.from_bytes(bytes, byteorder=byte_order) + return self.mb.getitem(addr) - def set_memory_value(self, addr, value, num_bytes=1, byte_order='big'): + def set_memory_value(self, addr, value): """ - Write consecutive bytes starting at a given memory address of the Game Boy's current memory state. + Write one byte to a given memory address of the Game Boy's current memory state. This will not directly give you access to all switchable memory banks. @@ -342,9 +339,7 @@ def set_memory_value(self, addr, value, num_bytes=1, byte_order='big'): addr (int): Address to write the byte value (int): A byte of data """ - bytes = value.to_bytes(num_bytes, byteorder=byte_order) - for i, byte in enumerate(bytes): - self.mb.setitem(addr + i, byte) + self.mb.setitem(addr, value) def override_memory_value(self, rom_bank, addr, value): """ From 5bb82da6846aff55c612c3968f2bb60c2e89d135 Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Tue, 7 Nov 2023 11:33:46 -0500 Subject: [PATCH 37/74] Add sprite memory addresses --- .../data/memory_addrs/sprites.py | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/sprites.py diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/sprites.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/sprites.py new file mode 100644 index 000000000..17ddcf984 --- /dev/null +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/sprites.py @@ -0,0 +1,38 @@ +''' +Memory addresses and descriptions taken from +https://datacrystal.romhacking.net/wiki/Pok%C3%A9mon_Red/Blue:RAM_map +''' + +from enum import Enum + +class SpriteBaseAddrs(Enum): + PLAYER_SPRITE = 0xC100 # Player is ALWAYS sprite 0 + SPRITE_1 = 0xC110 + SPIRITE_2 = 0xC120 + SPRITE_3 = 0xC130 + SPRITE_4 = 0xC140 + SPRITE_5 = 0xC150 + SPRITE_6 = 0xC160 + SPRITE_7 = 0xC170 + SPRITE_8 = 0xC180 + SPRITE_9 = 0xC190 + SPRITE_10 = 0xC1A0 + SPRITE_11 = 0xC1B0 + SPRITE_12 = 0xC1C0 + SPRITE_13 = 0xC1D0 + SPRITE_14 = 0xC1E0 + SPRITE_15 = 0xC1F0 + +class SpriteMemoryOffsets(Enum): + PICTURE_ID = 0x0 + MOVEMENT_STATUS = 0x1 # (0: uninitialized, 1: ready, 2: delayed, 3: moving) + # TODO: Figure out exactly what this data looks like + IMAGE_INDEX = 0x2 # (changed on update, $ff if off screen, includes facing direction, progress in walking animation and a sprite-specific offset) + Y_SCREEN_POS_D = 0x3 # Y screen position delta (-1,0 or 1; added to c1x4 on each walking animation update) + Y_SCREEN_POS = 0x4 # Y screen position (in pixels, always 4 pixels above grid which makes sprites appear to be in the center of a tile) + X_SCREEN_POS_D = 0x5 # X screen position delta (-1,0 or 1; added to c1x6 on each walking animation update) + X_SCREEN_POS = 0x6 # X screen position (in pixels, snaps to grid if not currently walking) + INTRA_ANIMATION_FRAME_COUNTER = 0x7 # intra-animation-frame counter (counting upwards to 4 until c1x8 is incremented) + ANIMATION_FRAME_COUNTER = 0x8 # animation frame counter (increased every 4 updates, hold four states (totalling to 16 walking frames) + FACING_DIRECTION = 0x9 # facing direction (0: down, 4: up, 8: left, $c: right) + From 65389fe66a475c948eb640ebbf726615d475b2e4 Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Tue, 7 Nov 2023 11:34:39 -0500 Subject: [PATCH 38/74] Add function to read multibyte data Add a function in the game wrapper to read multibyte data (in this case a pointer). this is almost certainly a feature that should either go in PyBoy proper or not exists at all (just manually reading consecutive bytes and adding them was the previous way), but it's being included here for now for ease of use and can be removed later if deemed necessary. --- .../game_wrapper_pokemon_gen1.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py index c54672bb9..9801e3c8d 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py @@ -14,7 +14,7 @@ from ..base_plugin import PyBoyGameWrapper from .core.gen_1_memory_manager import Gen1MemoryManager from .utils import get_character_index, STRING_TERMINATOR, ASCII_DELTA -from data.constants.status import Statuses +from .data.constants.status import Statuses PKMN_SIZE = 0x2C BYTE_ORDER = 'big' @@ -35,6 +35,12 @@ class GameWrapperPokemonGen1(PyBoyGameWrapper): """ cartridge_title = None + def _read_multibyte_value(self, addr, num_bytes): + val = 0 + for i in range(num_bytes): + val += self.pyboy.get_memory_value(addr+i) << i*8 + return val + def __init__(self, *args, **kwargs): self.shape = (20, 18) super().__init__(*args, game_area_section=(0, 0) + self.shape, game_area_wrap_around=True, **kwargs) @@ -62,7 +68,7 @@ def _get_screen_background_tilemap(self): def _get_screen_walkable_matrix(self): walkable_tiles_indexes = [] - collision_ptr = self.pyboy.get_memory_value(0xD530) + (self.pyboy.get_memory_value(0xD531) << 8) + collision_ptr = self._read_multibyte_value(0xD530, num_bytes=2) tileset_type = self.pyboy.get_memory_value(0xFFD7) if tileset_type > 0: grass_tile_index = self.pyboy.get_memory_value(0xD535) From efdb89a6b48c482e64ba41e62fd7d267c274b649 Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Tue, 7 Nov 2023 11:36:44 -0500 Subject: [PATCH 39/74] Update pokemon.py to use newly named PokemonMemoryOffets enum --- pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py index 38de2c6a5..bdead4f4e 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py @@ -1,4 +1,4 @@ -from ..data.memory_addrs.pokemon import PokemonBaseAddrs, PokemonOffsets +from ..data.memory_addrs.pokemon import PokemonBaseAddrs, PokemonMemoryOffsets from ..data.constants.pokemon import PokemonIds, _POKEMON_NAMES, _POKEMON_POKEDEX_INDEX from .move import Move @@ -142,9 +142,9 @@ def _load_pokemon_from_address(pyboy, pokemon_base_address): pokemon_values = [] - for offset_enum in PokemonOffsets: + for offset_enum in PokemonMemoryOffsets: offset, num_bytes = offset_enum.value[0], offset_enum.value[1] - memory_value = pyboy.get_memory_value(pokemon_base_address+offset, num_bytes) + memory_value = pyboy.get_memory_value(pokemon_base_address+offset) pokemon_values.append(memory_value) return Pokemon(*pokemon_values) From c7aa8f49a616850e4dab33d334a0774a1e667c86 Mon Sep 17 00:00:00 2001 From: SnarkAttack Date: Tue, 7 Nov 2023 15:09:18 -0500 Subject: [PATCH 40/74] remove Gen1MemoryManager class, was just unnecessary level of encapsulation --- .../core/gen_1_memory_manager.pxd | 11 -- .../core/gen_1_memory_manager.py | 16 -- .../game_wrapper_pokemon_gen1.pxd | 3 +- .../game_wrapper_pokemon_gen1.py | 165 ++---------------- 4 files changed, 16 insertions(+), 179 deletions(-) delete mode 100644 pyboy/plugins/game_wrapper_pokemon_gen1/core/gen_1_memory_manager.pxd delete mode 100644 pyboy/plugins/game_wrapper_pokemon_gen1/core/gen_1_memory_manager.py diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/gen_1_memory_manager.pxd b/pyboy/plugins/game_wrapper_pokemon_gen1/core/gen_1_memory_manager.pxd deleted file mode 100644 index 91f9048c5..000000000 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/gen_1_memory_manager.pxd +++ /dev/null @@ -1,11 +0,0 @@ -# -# License: See LICENSE.md file -# GitHub: https://github.com/Baekalfen/PyBoy -# -from libc.stdint cimport uint8_t -from pyboy.pyboy cimport PyBoy -cimport cython - -cdef class Gen1MemoryManager: - cdef PyBoy pyboy - cdef str byte_order \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/gen_1_memory_manager.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/gen_1_memory_manager.py deleted file mode 100644 index 433054cc7..000000000 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/gen_1_memory_manager.py +++ /dev/null @@ -1,16 +0,0 @@ -from .pokemon import Pokemon - -# All info from https://datacrystal.romhacking.net/wiki/Pok%C3%A9mon_Red/Blue:RAM_map#ROM_banking - -SRAM = (0xA000, 0xBFFF) -WRAM = (0xC000, 0xDFFF) # Unsure of where this range ACTUALLY ends -HRAM = (0xFF80, 0xFFFE) - -class Gen1MemoryManager: - - def __init__(self, pyboy, byte_order='big'): - self.pyboy = pyboy - self.byte_order = byte_order - - def load_pokemon_from_party(self, party_location): - return Pokemon.load_pokemon_from_party(self.pyboy, party_location) \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.pxd b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.pxd index 3842a2374..499f68737 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.pxd +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.pxd @@ -4,8 +4,7 @@ # from libc.stdint cimport uint8_t from pyboy.plugins.base_plugin cimport PyBoyGameWrapper -from pyboy.plugins.game_wrapper_pokemon_gen1.core.gen_1_memory_manager cimport Gen1MemoryManager cimport cython cdef class GameWrapperPokemonGen1(PyBoyGameWrapper): - cdef Gen1MemoryManager memory_manager \ No newline at end of file + pass \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py index 9801e3c8d..f8b254c06 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py @@ -12,9 +12,10 @@ from pyboy.utils import WindowEvent from pyboy.logger import logger from ..base_plugin import PyBoyGameWrapper -from .core.gen_1_memory_manager import Gen1MemoryManager from .utils import get_character_index, STRING_TERMINATOR, ASCII_DELTA from .data.constants.status import Statuses +from .core.pokedex import Pokedex +from .core.pokemon import Pokemon PKMN_SIZE = 0x2C BYTE_ORDER = 'big' @@ -34,17 +35,10 @@ class GameWrapperPokemonGen1(PyBoyGameWrapper): If you call `print` on an instance of this object, it will show an overview of everything this object provides. """ cartridge_title = None - - def _read_multibyte_value(self, addr, num_bytes): - val = 0 - for i in range(num_bytes): - val += self.pyboy.get_memory_value(addr+i) << i*8 - return val - + def __init__(self, *args, **kwargs): self.shape = (20, 18) super().__init__(*args, game_area_section=(0, 0) + self.shape, game_area_wrap_around=True, **kwargs) - self.memory_manager = Gen1MemoryManager(self.pyboy) def enabled(self): return self.pyboy_argv.get("game_wrapper") and ((self.pyboy.cartridge_title() == "POKEMON RED") or @@ -131,45 +125,6 @@ def set_text(self, text, address): pass self.pyboy.set_memory_value(address + i, STRING_TERMINATOR) - def set_rom_text(self, text, bank, address): - i = 0 - for character in text: - try: - self.pyboy.override_memory_value(bank, address + i, get_character_index(character)) - i += 1 - except: - pass - - def set_player_name(self, name): - """ - Sets the player name. - - Args: - name (string): Name to be set (will be trimmed at 8 characters). - """ - self.set_text(name[:8], 0xD158) - - def get_player_name(self): - """ - Returns player name. - """ - return self.get_text(0xD158) - - def set_rival_name(self, name): - """ - Sets the rival name. - - Args: - name (string): Name to be set (will be trimmed at 8 characters). - """ - self.set_text(name[:8], 0xD34A) - - def get_rival_name(self): - """ - Returns rival name. - """ - return self.get_text(0xD34A) - def get_text(self, address, cap = 16): """ Retrieves a string from a given address. @@ -191,107 +146,17 @@ def get_text(self, address, cap = 16): i += 1 return text - def set_palette_to_darkness(self): - self.pyboy.set_memory_value(0xD35D, 6) - - def get_pokemon(self, party_index): - return self.memory_manager.load_pokemon_from_party(party_index) - - def set_player_monster_asleep(self, index): - self.set_player_monster_status(index, Statuses.ASLEEP) - - def set_player_monster_poisoned(self, index): - self.set_player_monster_status(index, Statuses.POISONED) - - def set_player_monster_burned(self, index): - self.set_player_monster_status(index, Statuses.BURNED) - - def set_player_monster_frozen(self, index): - self.set_player_monster_status(index, Statuses.FROZEN) - - def set_player_monster_paralyzed(self, index): - self.set_player_monster_status(index, Statuses.PARALYZED) - - def set_player_monster_no_ailment(self, index): - self.set_player_monster_status(index, 0) - - def get_player_money(self): - return self.get_int_at_address(0xD347, size=3) - - def set_active_player_monster_status(self, status): - self.pyboy.set_memory_value(0xD018, status) - - def set_active_player_monster_asleep(self): - self.set_active_player_monster_status(Statuses.ASLEEP) - - def set_active_player_monster_poisoned(self): - self.set_active_player_monster_status(Statuses.POISONED) - - def set_active_player_monster_burned(self): - self.set_active_player_monster_status(Statuses.BURNED) - - def set_active_player_monster_frozen(self): - self.set_active_player_monster_status(Statuses.FROZEN) - - def set_active_player_monster_paralyzed(self): - self.set_active_player_monster_status(Statuses.PARALYZED) - - def set_active_player_monster_no_ailment(self): - self.set_active_player_monster_status(0) - - def set_active_player_monster_move(self, index, move): - self.pyboy.set_memory_value(0xD01C + index, move) - - def set_active_opponent_monster_move(self, index, move): - self.pyboy.set_memory_value(0xCFED + index, move) - - def set_active_player_monster_nickname(self, nickname): - self.set_text(nickname[:10], 0xD009) - - def set_active_opponent_monster_nickname(self, nickname): - self.set_text(nickname[:10], 0xCFDA) - - def set_active_opponent_monster_status(self, status): - self.pyboy.set_memory_value(0xCFE9, status) - - def set_active_opponent_monster_asleep(self): - self.set_active_opponent_monster_status(Statuses.ASLEEP) - - def set_active_opponent_monster_poisoned(self): - self.set_active_opponent_monster_status(Statuses.POISONED) - - def set_active_opponent_monster_burned(self): - self.set_active_opponent_monster_status(Statuses.BURNED) - - def set_active_opponent_monster_frozen(self): - self.set_active_opponent_monster_status(Statuses.FROZEN) - - def set_active_opponent_monster_paralyzed(self): - self.set_active_opponent_monster_status(Statuses.PARALYZED) - - def set_active_opponent_monster_no_ailment(self): - self.set_active_opponent_monster_status(0) - - def heal_player_monster(self, index): - """ - Fully heals a player monster. - - Args: - index (int): Which monster to change (0-5). - """ - self.set_player_monster_no_ailment(index) - max_hp = self.get_player_monster_max_hp(index) - self.set_player_monster_current_hp(index, max_hp) - - def heal_active_player_monster(self): - self.set_active_player_monster_no_ailment() - max_hp = self.get_active_player_monster_max_hp() - self.set_active_player_monster_current_hp(max_hp) - - def is_battle_happening(self): - return self.pyboy.get_memory_value(0xD057) != 0 + def set_rom_text(self, text, bank, address): + i = 0 + for character in text: + try: + self.pyboy.override_memory_value(bank, address + i, get_character_index(character)) + i += 1 + except: + pass - def get_current_map(self): - return self.pyboy.get_memory_value(0xD35E) + def get_pokemon_from_party(self, party_index): + return Pokemon.load_pokemon_from_party(self.pyboy, party_index) - # TODO: Add player position functions + def get_pokedex(self): + return Pokedex.load_pokedex(self.pyboy) \ No newline at end of file From da33d44c32d1a3809e0f3c6316375490a1e5bb79 Mon Sep 17 00:00:00 2001 From: SnarkAttack Date: Tue, 7 Nov 2023 15:10:43 -0500 Subject: [PATCH 41/74] Update Pokemon class to include 'hidden' level field and added utility funcitons to correctly load 2 byte values --- .../game_wrapper_pokemon_gen1/core/pokemon.py | 39 +++++++++++++------ .../data/memory_addrs/pokemon.py | 21 +++++----- .../game_wrapper_pokemon_gen1/utils.py | 27 +++++++++++++ 3 files changed, 65 insertions(+), 22 deletions(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py index bdead4f4e..94f3d836a 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py @@ -1,12 +1,14 @@ from ..data.memory_addrs.pokemon import PokemonBaseAddrs, PokemonMemoryOffsets from ..data.constants.pokemon import PokemonIds, _POKEMON_NAMES, _POKEMON_POKEDEX_INDEX from .move import Move +from ..utils import get_int_at_address class Pokemon: def __init__(self, pokemon_id, current_hp, + box_level, status, type_1, type_2, @@ -29,12 +31,13 @@ def __init__(self, pp_move_3, pp_move_4, level, - max_hp, - attack, - defense, - speed, - special): - self.pokemon_id = pokemon_id + max_hp=0, + attack=0, + defense=0, + speed=0, + special=0, + in_party=False): + self.pokemon_id = PokemonIds(pokemon_id) self.current_hp = current_hp self.status = status self.type_1 = type_1 @@ -48,14 +51,19 @@ def __init__(self, self.attack_defense_iv = attack_defense_iv self.speed_special_iv = speed_special_iv self.pp_moves = [pp_move_1, pp_move_2, pp_move_3, pp_move_4] - self.level = level + self.level = level if in_party else box_level # Stat order same as EV order self.stats = [max_hp, attack, defense, speed, special] + self.in_party = in_party @property def name(self): return Pokemon.get_pokemon_name_from_id(self.pokemon_id) + @property + def pokedex_num(self): + return Pokemon.get_pokedex_id_from_pokemon_id(self.pokemon_id) + @property def move_1(self): return self.moves[0] @@ -138,22 +146,29 @@ def get_pokedex_id_from_pokemon_id(pokemon_id): @staticmethod - def _load_pokemon_from_address(pyboy, pokemon_base_address): + def _load_pokemon_from_address(pyboy, pokemon_base_address, in_party): pokemon_values = [] + if in_party: + it = list(PokemonMemoryOffsets) + else: + # When checking a Pokemon in the box, it does not have the second + # level field or any of its stats saved in memory + it = list(PokemonMemoryOffsets)[:-6] + for offset_enum in PokemonMemoryOffsets: offset, num_bytes = offset_enum.value[0], offset_enum.value[1] - memory_value = pyboy.get_memory_value(pokemon_base_address+offset) + memory_value = get_int_at_address(pyboy, pokemon_base_address+offset, size=num_bytes) pokemon_values.append(memory_value) - return Pokemon(*pokemon_values) + return Pokemon(*pokemon_values, in_party) @classmethod def load_pokemon_from_party(cls, pyboy, party_location): - # party_location goes from 1 to 6 + # party_location goes from 1-6 pokemon_base_address = list(PokemonBaseAddrs)[party_location-1].value - return cls._load_pokemon_from_address(pyboy, pokemon_base_address) + return cls._load_pokemon_from_address(pyboy, pokemon_base_address, in_party=True) def _generate_move_str(self): s = f"Moves:\n" diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/pokemon.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/pokemon.py index 43dac970d..d15272465 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/pokemon.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/pokemon.py @@ -14,16 +14,17 @@ class PokemonBaseAddrs(Enum): class PokemonMemoryOffsets(Enum): ID = (0x0, 1) CURRENT_HP = (0x1, 2) - STATUS = (0x3, 1) - TYPE_1 = (0x4, 1) - TYPE_2 = (0x5, 1) - CATCH_RATE = (0x6, 1) - MOVE_1 = (0x7, 1) - MOVE_2 = (0x8, 1) - MOVE_3 = (0x9, 1) - MOVE_4 = (0xA, 1) - TRAINER_ID = (0xB, 2) - EXPERIENCE = (0xD, 3) + BOX_LEVEL = (0x3, 1) + STATUS = (0x4, 1) + TYPE_1 = (0x5, 1) + TYPE_2 = (0x6, 1) + CATCH_RATE = (0x7, 1) + MOVE_1 = (0x8, 1) + MOVE_2 = (0x9, 1) + MOVE_3 = (0xA, 1) + MOVE_4 = (0xB, 1) + TRAINER_ID = (0xC, 2) + EXPERIENCE = (0xE, 3) HP_EV = (0x11, 2) ATTACK_EV = (0x13, 2) DEFENSE_EV = (0x15, 2) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/utils.py b/pyboy/plugins/game_wrapper_pokemon_gen1/utils.py index f027bd403..ac8e07f15 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/utils.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/utils.py @@ -1,3 +1,5 @@ +import numpy as np + STRING_TERMINATOR = 80 ASCII_DELTA = 63 @@ -16,3 +18,28 @@ def get_character_index(character): # number return index + 197 return index + ASCII_DELTA + +def read_multibyte_value(pyboy, addr, num_bytes): + val = 0 + for i in range(num_bytes): + val += pyboy.get_memory_value(addr+i) << i*8 + return val + +def get_int_at_address(pyboy, address, size=2, byte_order='big'): + """Returns an integer from a given address of a specified size.""" + bytes = [] + for i in range(size): + bytes.append(pyboy.get_memory_value(address + i)) + return int.from_bytes(bytes, byteorder=byte_order) + +def set_int_at_address(pyboy, address, value, size=2, byte_order='big'): + """Sets an integer at a given address of a specified size.""" + bytes = value.to_bytes(2, byteorder=byte_order) + i = 0 + for byte in bytes: + pyboy.set_memory_value(address + i, byte) + i += 1 + +def bitfield(n): + return [1 if digit=='1' else 0 for digit in bin(n)[2:]] + From c8e056320dd461c1d5ae4e36e1cfc2712d5473b6 Mon Sep 17 00:00:00 2001 From: SnarkAttack Date: Tue, 7 Nov 2023 15:11:11 -0500 Subject: [PATCH 42/74] Add POkedex class --- .../game_wrapper_pokemon_gen1/core/pokedex.py | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 pyboy/plugins/game_wrapper_pokemon_gen1/core/pokedex.py diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokedex.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokedex.py new file mode 100644 index 000000000..fa3c80939 --- /dev/null +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokedex.py @@ -0,0 +1,57 @@ +from pyboy.plugins.game_wrapper_pokemon_gen1.utils import bitfield +from pyboy.plugins.game_wrapper_pokemon_gen1.core.pokemon import Pokemon + +# TODO: Technically with the project structure these should be in data/memory_addrs, +# but these are literally the only memory addresses we need so they lives here for now. +# Also probably move if we eventually have a flag to check Japanese vs international ROM + +POKEDEX_CAUGHT_START_ADDR_INT = 0xD2F7 +POKEDEX_CAUGHT_END_ADDR_INT = 0xD309 +POKEDEX_SEEN_START_ADDR_INT = 0xD30A +POKEDEX_SEEN_END_ADDR_INT = 0xD31C + + +class Pokedex: + + def __init__(self, + caught_list, + seen_list): + + self._caught_list = caught_list + self._seen_list = seen_list + + @staticmethod + def get_pokedex_range_bits(pyboy, start_addr, end_addr): + + bit_list = [] + + addr = start_addr + + while addr <= end_addr: + pokedex_byte = pyboy.get_memory_value(addr) + byte_bit_list = bitfield(pokedex_byte) + bit_list.extend(byte_bit_list) + addr += 1 + + return bit_list + + + @staticmethod + def load_pokedex(pyboy): + caught_pokemon = Pokedex.get_pokedex_range_bits(pyboy, POKEDEX_CAUGHT_START_ADDR_INT, POKEDEX_CAUGHT_END_ADDR_INT) + seen_pokemon = Pokedex.get_pokedex_range_bits(pyboy, POKEDEX_SEEN_START_ADDR_INT, POKEDEX_SEEN_END_ADDR_INT) + + return Pokedex(caught_pokemon, seen_pokemon) + + + def get_number_pokemon_caught(self): + return sum(self._caught_list) + + def get_number_pokemon_seen(self): + return sum(self._seen_list) + + def have_caught_pokemon(self, pokemon_id): + return self._caught_list[Pokemon.get_pokedex_id_from_pokemon_id(pokemon_id).value] == 1 + + def have_seen_pokemon(self, pokemon_id): + return self._seen_list[Pokemon.get_pokedex_id_from_pokemon_id(pokemon_id).value] == 1 \ No newline at end of file From a4024095be633e8bb5c2375eca2b09b7a199140e Mon Sep 17 00:00:00 2001 From: SnarkAttack Date: Tue, 7 Nov 2023 15:57:07 -0500 Subject: [PATCH 43/74] Add player money get --- .../game_wrapper_pokemon_gen1/data/memory_addrs/misc.py | 2 ++ .../game_wrapper_pokemon_gen1.py | 8 ++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/misc.py diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/misc.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/misc.py new file mode 100644 index 000000000..3b57b1829 --- /dev/null +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/misc.py @@ -0,0 +1,2 @@ + +MONEY_ADDR = (0xD347, 3) \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py index f8b254c06..5517d8cf0 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py @@ -12,8 +12,9 @@ from pyboy.utils import WindowEvent from pyboy.logger import logger from ..base_plugin import PyBoyGameWrapper -from .utils import get_character_index, STRING_TERMINATOR, ASCII_DELTA +from .utils import get_character_index, get_int_at_address, STRING_TERMINATOR, ASCII_DELTA from .data.constants.status import Statuses +from .data.memory_addrs.misc import MONEY_ADDR from .core.pokedex import Pokedex from .core.pokemon import Pokemon @@ -159,4 +160,7 @@ def get_pokemon_from_party(self, party_index): return Pokemon.load_pokemon_from_party(self.pyboy, party_index) def get_pokedex(self): - return Pokedex.load_pokedex(self.pyboy) \ No newline at end of file + return Pokedex.load_pokedex(self.pyboy) + + def get_player_money(self): + return get_int_at_address(self.pyboy, MONEY_ADDR[0], MONEY_ADDR[1]) \ No newline at end of file From 5c6b76e8043f9b46f13893d43687b72f7ad78c84 Mon Sep 17 00:00:00 2001 From: SnarkAttack Date: Wed, 8 Nov 2023 09:37:01 -0500 Subject: [PATCH 44/74] Memory manager class is back baby It turns out there are a couple of different ways memory can be stored in multibyte chunks (memory pointers, hex values, bcd) and there is not necessarily good indicators of which is which. To ease the burden of importing various different memory accessing functions, it's just all going back into a memory mamanger class for now --- .../core/mem_manager.pxd | 10 ++++++++++ .../game_wrapper_pokemon_gen1/core/mem_manager.py | 15 +++++++++++++++ .../game_wrapper_pokemon_gen1.pxd | 3 ++- .../game_wrapper_pokemon_gen1.py | 2 ++ 4 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.pxd create mode 100644 pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.pxd b/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.pxd new file mode 100644 index 000000000..28a626c1b --- /dev/null +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.pxd @@ -0,0 +1,10 @@ +# +# License: See LICENSE.md file +# GitHub: https://github.com/Baekalfen/PyBoy +# +from libc.stdint cimport uint8_t +from pyboy.pyboy cimport PyBoy +cimport cython + +cdef class MemoryManager: + cdef PyBoy pyboy \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py new file mode 100644 index 000000000..784836d88 --- /dev/null +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py @@ -0,0 +1,15 @@ + + +class MemoryManager(): + + def __init__(self, pyboy): + self.pyboy = pyboy + + def read_byte(self, addr): + return self.pyboy.get_memory_value(addr) + + def read_int_from_bytes(self, addr, num_bytes): + byte_str = "" + for i in range(num_bytes): + byte_str += "%x"%self.pyboy.get_memory_value(addr) + return int(byte_str) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.pxd b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.pxd index 499f68737..1557a8255 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.pxd +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.pxd @@ -4,7 +4,8 @@ # from libc.stdint cimport uint8_t from pyboy.plugins.base_plugin cimport PyBoyGameWrapper +from pyboy.plugins.game_wrapper_pokemon_gen1.core.mem_manager cimport MemoryManager cimport cython cdef class GameWrapperPokemonGen1(PyBoyGameWrapper): - pass \ No newline at end of file + cdef MemoryManager mem_manager \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py index 5517d8cf0..30c55e51a 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py @@ -17,6 +17,7 @@ from .data.memory_addrs.misc import MONEY_ADDR from .core.pokedex import Pokedex from .core.pokemon import Pokemon +from .core.mem_manager import MemoryManager PKMN_SIZE = 0x2C BYTE_ORDER = 'big' @@ -40,6 +41,7 @@ class GameWrapperPokemonGen1(PyBoyGameWrapper): def __init__(self, *args, **kwargs): self.shape = (20, 18) super().__init__(*args, game_area_section=(0, 0) + self.shape, game_area_wrap_around=True, **kwargs) + self.mem_manager = MemoryManager(self.pyboy) def enabled(self): return self.pyboy_argv.get("game_wrapper") and ((self.pyboy.cartridge_title() == "POKEMON RED") or From bb0f6268c979ba95daa6dc386232db553de166ed Mon Sep 17 00:00:00 2001 From: SnarkAttack Date: Wed, 8 Nov 2023 09:43:33 -0500 Subject: [PATCH 45/74] Define explicit function calls for different type of memory access --- .../core/mem_manager.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py index 784836d88..ad57d2a38 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py @@ -8,8 +8,22 @@ def __init__(self, pyboy): def read_byte(self, addr): return self.pyboy.get_memory_value(addr) - def read_int_from_bytes(self, addr, num_bytes): + def read_address_from_bytes(self, addr, num_bytes): + p_addr = 0 + for i in range(num_bytes): + p_addr += self.pyboy.get_memory_value(addr+i) << i*8 + return p_addr + + def read_hex_from_bytes(self, addr, num_bytes): + bytes = [] + for i in range(num_bytes): + bytes.append(self.pyboy.get_memory_value(addr + i)) + # Do not believe there is ever a case where we would + # need to read this in little endian for Pokemon gen 1 + return int.from_bytes(bytes, byteorder='big') + + def read_bcd_from_bytes(self, addr, num_bytes): byte_str = "" for i in range(num_bytes): byte_str += "%x"%self.pyboy.get_memory_value(addr) - return int(byte_str) + return int(byte_str) \ No newline at end of file From 7766dfa92fbc1ab17e6e26a26ff651e55fd19115 Mon Sep 17 00:00:00 2001 From: SnarkAttack Date: Wed, 8 Nov 2023 09:44:42 -0500 Subject: [PATCH 46/74] rename function calls to indicate these are memory reads --- pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py index ad57d2a38..c07bee4e2 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py @@ -8,13 +8,13 @@ def __init__(self, pyboy): def read_byte(self, addr): return self.pyboy.get_memory_value(addr) - def read_address_from_bytes(self, addr, num_bytes): + def read_address_from_memory(self, addr, num_bytes): p_addr = 0 for i in range(num_bytes): p_addr += self.pyboy.get_memory_value(addr+i) << i*8 return p_addr - def read_hex_from_bytes(self, addr, num_bytes): + def read_hex_from_memory(self, addr, num_bytes): bytes = [] for i in range(num_bytes): bytes.append(self.pyboy.get_memory_value(addr + i)) @@ -22,7 +22,7 @@ def read_hex_from_bytes(self, addr, num_bytes): # need to read this in little endian for Pokemon gen 1 return int.from_bytes(bytes, byteorder='big') - def read_bcd_from_bytes(self, addr, num_bytes): + def read_bcd_from_memory(self, addr, num_bytes): byte_str = "" for i in range(num_bytes): byte_str += "%x"%self.pyboy.get_memory_value(addr) From 5d1a66b5765a97a79ea9278ec9b27c50db5dbbc1 Mon Sep 17 00:00:00 2001 From: SnarkAttack Date: Wed, 8 Nov 2023 11:24:45 -0500 Subject: [PATCH 47/74] Change all memory access calls to now go through MemoryManager class --- .../core/mem_manager.py | 87 +++++++++++++++++-- .../game_wrapper_pokemon_gen1/core/pokedex.py | 44 ++++------ .../game_wrapper_pokemon_gen1/core/pokemon.py | 9 +- .../game_wrapper_pokemon_gen1.py | 51 +---------- .../game_wrapper_pokemon_gen1/utils.py | 45 ---------- 5 files changed, 103 insertions(+), 133 deletions(-) delete mode 100644 pyboy/plugins/game_wrapper_pokemon_gen1/utils.py diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py index c07bee4e2..784dc15ef 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py @@ -1,20 +1,50 @@ +STRING_TERMINATOR = 80 +ASCII_DELTA = 63 +MAX_STRING_LENGTH = 16 class MemoryManager(): def __init__(self, pyboy): self.pyboy = pyboy - def read_byte(self, addr): + @staticmethod + def _byte_to_bitfield(n, reverse : bool): + # Force bit extension to 10 chars; 2 for '0x' and 8 for the bits + bitlist = [1 if digit=='1' else 0 for digit in format(n, '#010b')[2:]] + + if reverse: + bitlist.reverse() + + return bitlist + + @staticmethod + def get_character_index(character): + if character == ' ': + return 0x7F + if character == '?': + return 0xE6 + if character == '!': + return 0xE7 + if character == 'é': + return 0xBA + + index = ord(character) + if index > 47 and index < 58: + # number + return index + 197 + return index + ASCII_DELTA + + def _read_byte(self, addr): return self.pyboy.get_memory_value(addr) - def read_address_from_memory(self, addr, num_bytes): + def read_address_from_memory(self, addr, num_bytes=1): p_addr = 0 for i in range(num_bytes): p_addr += self.pyboy.get_memory_value(addr+i) << i*8 return p_addr - def read_hex_from_memory(self, addr, num_bytes): + def read_hex_from_memory(self, addr, num_bytes=1): bytes = [] for i in range(num_bytes): bytes.append(self.pyboy.get_memory_value(addr + i)) @@ -22,8 +52,53 @@ def read_hex_from_memory(self, addr, num_bytes): # need to read this in little endian for Pokemon gen 1 return int.from_bytes(bytes, byteorder='big') - def read_bcd_from_memory(self, addr, num_bytes): + def read_bcd_from_memory(self, addr, num_bytes=1): byte_str = "" for i in range(num_bytes): - byte_str += "%x"%self.pyboy.get_memory_value(addr) - return int(byte_str) \ No newline at end of file + byte_str += "%x"%self.pyboy.get_memory_value(addr+i) + return int(byte_str) + + def read_bitfield_from_memory(self, addr, num_bytes=1, reverse=False): + bits = [] + for i in range(num_bytes): + bits.extend(MemoryManager._byte_to_bitfield(self._read_byte(addr+i), reverse)) + return bits + + def read_text_from_memory(self, address, num_bytes): + """ + Retrieves a string from a given address. + + Args: + address (int): Address from where to retrieve text from. + cap (int): Maximum expected length of string (default: 16). + """ + # Make sure string to write not too large + assert num_bytes <= MAX_STRING_LENGTH + text = '' + for i in range(num_bytes): + value = self._read_byte(address + i) + text += chr(value - ASCII_DELTA) + return text + + # def set_text(self, text, address): + # """Sets text at address. + + # Will always add a string terminator (80) at the end. + # """ + # i = 0 + # for character in text: + # try: + # self.pyboy.set_memory_value(address + i, MemoryManager.get_character_index(character)) + # i += 1 + # except: + # pass + # self.pyboy.set_memory_value(address + i, STRING_TERMINATOR) + + # def set_rom_text(self, text, bank, address): + # i = 0 + # for character in text: + # try: + # self.pyboy.override_memory_value(bank, address + i, get_character_index(character)) + # i += 1 + # except: + # pass \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokedex.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokedex.py index fa3c80939..9de770c1b 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokedex.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokedex.py @@ -1,57 +1,43 @@ -from pyboy.plugins.game_wrapper_pokemon_gen1.utils import bitfield from pyboy.plugins.game_wrapper_pokemon_gen1.core.pokemon import Pokemon # TODO: Technically with the project structure these should be in data/memory_addrs, # but these are literally the only memory addresses we need so they lives here for now. # Also probably move if we eventually have a flag to check Japanese vs international ROM -POKEDEX_CAUGHT_START_ADDR_INT = 0xD2F7 -POKEDEX_CAUGHT_END_ADDR_INT = 0xD309 -POKEDEX_SEEN_START_ADDR_INT = 0xD30A -POKEDEX_SEEN_END_ADDR_INT = 0xD31C +POKEDEX_CAUGHT_ADDR_INT = (0xD2F7, 19) +POKEDEX_SEEN_ADDR_INT = (0xD30A, 19) class Pokedex: def __init__(self, - caught_list, - seen_list): + caught_pokemon, + seen_pokemon): - self._caught_list = caught_list - self._seen_list = seen_list + self._caught_pokemon = caught_pokemon + self._seen_pokemon = seen_pokemon @staticmethod - def get_pokedex_range_bits(pyboy, start_addr, end_addr): - - bit_list = [] - - addr = start_addr - - while addr <= end_addr: - pokedex_byte = pyboy.get_memory_value(addr) - byte_bit_list = bitfield(pokedex_byte) - bit_list.extend(byte_bit_list) - addr += 1 + def get_pokedex_range_bits(mem_manager, addr, num_bytes): + return mem_manager.read_bitfield_from_memory(addr, num_bytes, reverse=True) - return bit_list - @staticmethod - def load_pokedex(pyboy): - caught_pokemon = Pokedex.get_pokedex_range_bits(pyboy, POKEDEX_CAUGHT_START_ADDR_INT, POKEDEX_CAUGHT_END_ADDR_INT) - seen_pokemon = Pokedex.get_pokedex_range_bits(pyboy, POKEDEX_SEEN_START_ADDR_INT, POKEDEX_SEEN_END_ADDR_INT) + def load_pokedex(mem_manager): + caught_pokemon = Pokedex.get_pokedex_range_bits(mem_manager, POKEDEX_CAUGHT_ADDR_INT[0], num_bytes=POKEDEX_CAUGHT_ADDR_INT[1]) + seen_pokemon = Pokedex.get_pokedex_range_bits(mem_manager, POKEDEX_SEEN_ADDR_INT[0], num_bytes=POKEDEX_SEEN_ADDR_INT[1]) return Pokedex(caught_pokemon, seen_pokemon) def get_number_pokemon_caught(self): - return sum(self._caught_list) + return sum(self._caught_pokemon) def get_number_pokemon_seen(self): - return sum(self._seen_list) + return sum(self._seen_pokemon) def have_caught_pokemon(self, pokemon_id): - return self._caught_list[Pokemon.get_pokedex_id_from_pokemon_id(pokemon_id).value] == 1 + return self._caught_pokemon[Pokemon.get_pokedex_id_from_pokemon_id(pokemon_id)-1] == 1 def have_seen_pokemon(self, pokemon_id): - return self._seen_list[Pokemon.get_pokedex_id_from_pokemon_id(pokemon_id).value] == 1 \ No newline at end of file + return self._seen_pokemon[Pokemon.get_pokedex_id_from_pokemon_id(pokemon_id)-1] == 1 \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py index 94f3d836a..4109d1827 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py @@ -1,7 +1,6 @@ from ..data.memory_addrs.pokemon import PokemonBaseAddrs, PokemonMemoryOffsets from ..data.constants.pokemon import PokemonIds, _POKEMON_NAMES, _POKEMON_POKEDEX_INDEX from .move import Move -from ..utils import get_int_at_address class Pokemon: @@ -146,7 +145,7 @@ def get_pokedex_id_from_pokemon_id(pokemon_id): @staticmethod - def _load_pokemon_from_address(pyboy, pokemon_base_address, in_party): + def _load_pokemon_from_address(mem_manager, pokemon_base_address, in_party): pokemon_values = [] @@ -159,16 +158,16 @@ def _load_pokemon_from_address(pyboy, pokemon_base_address, in_party): for offset_enum in PokemonMemoryOffsets: offset, num_bytes = offset_enum.value[0], offset_enum.value[1] - memory_value = get_int_at_address(pyboy, pokemon_base_address+offset, size=num_bytes) + memory_value = mem_manager.read_hex_from_memory(pokemon_base_address+offset, num_bytes) pokemon_values.append(memory_value) return Pokemon(*pokemon_values, in_party) @classmethod - def load_pokemon_from_party(cls, pyboy, party_location): + def load_pokemon_from_party(cls, mem_manager, party_location): # party_location goes from 1-6 pokemon_base_address = list(PokemonBaseAddrs)[party_location-1].value - return cls._load_pokemon_from_address(pyboy, pokemon_base_address, in_party=True) + return cls._load_pokemon_from_address(mem_manager, pokemon_base_address, in_party=True) def _generate_move_str(self): s = f"Moves:\n" diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py index 30c55e51a..e2b6e49d4 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py @@ -12,7 +12,6 @@ from pyboy.utils import WindowEvent from pyboy.logger import logger from ..base_plugin import PyBoyGameWrapper -from .utils import get_character_index, get_int_at_address, STRING_TERMINATOR, ASCII_DELTA from .data.constants.status import Statuses from .data.memory_addrs.misc import MONEY_ADDR from .core.pokedex import Pokedex @@ -114,55 +113,11 @@ def __repr__(self): ) # yapf: enable - def set_text(self, text, address): - """Sets text at address. - - Will always add a string terminator (80) at the end. - """ - i = 0 - for character in text: - try: - self.pyboy.set_memory_value(address + i, get_character_index(character)) - i += 1 - except: - pass - self.pyboy.set_memory_value(address + i, STRING_TERMINATOR) - - def get_text(self, address, cap = 16): - """ - Retrieves a string from a given address. - - Args: - address (int): Address from where to retrieve text from. - cap (int): Maximum expected length of string (default: 16). - """ - i = 0 - text = '' - while i < cap: - value = self.pyboy.get_memory_value(address + i) - try: - text += chr(value - ASCII_DELTA) - except: - pass - if value == STRING_TERMINATOR: - break - i += 1 - return text - - def set_rom_text(self, text, bank, address): - i = 0 - for character in text: - try: - self.pyboy.override_memory_value(bank, address + i, get_character_index(character)) - i += 1 - except: - pass - def get_pokemon_from_party(self, party_index): - return Pokemon.load_pokemon_from_party(self.pyboy, party_index) + return Pokemon.load_pokemon_from_party(self.mem_manager, party_index) def get_pokedex(self): - return Pokedex.load_pokedex(self.pyboy) + return Pokedex.load_pokedex(self.mem_manager) def get_player_money(self): - return get_int_at_address(self.pyboy, MONEY_ADDR[0], MONEY_ADDR[1]) \ No newline at end of file + return self.mem_manager.read_bcd_from_memory(MONEY_ADDR[0], MONEY_ADDR[1]) \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/utils.py b/pyboy/plugins/game_wrapper_pokemon_gen1/utils.py deleted file mode 100644 index ac8e07f15..000000000 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/utils.py +++ /dev/null @@ -1,45 +0,0 @@ -import numpy as np - -STRING_TERMINATOR = 80 -ASCII_DELTA = 63 - -def get_character_index(character): - if character == ' ': - return 0x7F - if character == '?': - return 0xE6 - if character == '!': - return 0xE7 - if character == 'é': - return 0xBA - - index = ord(character) - if index > 47 and index < 58: - # number - return index + 197 - return index + ASCII_DELTA - -def read_multibyte_value(pyboy, addr, num_bytes): - val = 0 - for i in range(num_bytes): - val += pyboy.get_memory_value(addr+i) << i*8 - return val - -def get_int_at_address(pyboy, address, size=2, byte_order='big'): - """Returns an integer from a given address of a specified size.""" - bytes = [] - for i in range(size): - bytes.append(pyboy.get_memory_value(address + i)) - return int.from_bytes(bytes, byteorder=byte_order) - -def set_int_at_address(pyboy, address, value, size=2, byte_order='big'): - """Sets an integer at a given address of a specified size.""" - bytes = value.to_bytes(2, byteorder=byte_order) - i = 0 - for byte in bytes: - pyboy.set_memory_value(address + i, byte) - i += 1 - -def bitfield(n): - return [1 if digit=='1' else 0 for digit in bin(n)[2:]] - From 2f295f16acee8e27004d01d3b2dabef694bc1c88 Mon Sep 17 00:00:00 2001 From: SnarkAttack Date: Wed, 8 Nov 2023 12:22:45 -0500 Subject: [PATCH 48/74] Fix issue where strings shorted than the adresses they could occupy were not terminated on end string character --- pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py index 784dc15ef..26f78141d 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py @@ -77,6 +77,8 @@ def read_text_from_memory(self, address, num_bytes): text = '' for i in range(num_bytes): value = self._read_byte(address + i) + if value == STRING_TERMINATOR: + break text += chr(value - ASCII_DELTA) return text From bf7d90a6b8fb8a748bcaf23f0bf62ce401a6ff1f Mon Sep 17 00:00:00 2001 From: SnarkAttack Date: Wed, 8 Nov 2023 12:34:17 -0500 Subject: [PATCH 49/74] Fix bugs in/discovered by Player class --- .../game_wrapper_pokemon_gen1/core/player.py | 39 +++++++++++++++++++ .../data/memory_addrs/player.py | 7 ++++ .../game_wrapper_pokemon_gen1.py | 5 ++- 3 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py create mode 100644 pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/player.py diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py new file mode 100644 index 000000000..46d87407a --- /dev/null +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py @@ -0,0 +1,39 @@ +from ..data.memory_addrs.player import PlayerAddresses +from ..data.constants.pokemon import PokemonIds + +class Player: + + def __init__(self, + name, + pokemon_in_party, + badges, + money): + + self._name = name + self._pokemon_in_party = pokemon_in_party + self._badges = badges + self._money = money + + @staticmethod + def load_player(mem_manager): + + name = mem_manager.read_text_from_memory(PlayerAddresses.NAME[0], PlayerAddresses.NAME[1]) + + num_pokemon_in_party = mem_manager.read_hex_from_memory(PlayerAddresses.NUM_POKEMON_IN_PARTY[0]) + + pokemon_in_party = [PokemonIds(mem_manager.read_hex_from_memory(PlayerAddresses.NUM_POKEMON_IN_PARTY[0]+i+1)) + for i in range(num_pokemon_in_party)] + + badges = mem_manager.read_bitfield_from_memory(PlayerAddresses.BADGES[0]) + + money = mem_manager.read_bcd_from_memory(PlayerAddresses.MONEY[0], PlayerAddresses.MONEY[1]) + + return Player(name, pokemon_in_party, badges, money) + + @property + def num_pokemon_in_party(self): + return len(self._pokemon_in_party) + + @property + def num_badges(self): + return sum(self._badges) \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/player.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/player.py new file mode 100644 index 000000000..3c32bc87e --- /dev/null +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/player.py @@ -0,0 +1,7 @@ +from enum import Enum + +class PlayerAddresses: + NAME = (0xD158, 10) + NUM_POKEMON_IN_PARTY = (0xD163, 1) + BADGES = (0xD356, 1) + MONEY = (0xD347, 3) \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py index e2b6e49d4..e32950f55 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py @@ -16,6 +16,7 @@ from .data.memory_addrs.misc import MONEY_ADDR from .core.pokedex import Pokedex from .core.pokemon import Pokemon +from .core.player import Player from .core.mem_manager import MemoryManager PKMN_SIZE = 0x2C @@ -119,5 +120,5 @@ def get_pokemon_from_party(self, party_index): def get_pokedex(self): return Pokedex.load_pokedex(self.mem_manager) - def get_player_money(self): - return self.mem_manager.read_bcd_from_memory(MONEY_ADDR[0], MONEY_ADDR[1]) \ No newline at end of file + def get_player(self): + return Player.load_player(self.mem_manager) \ No newline at end of file From a573f84200e4ed15b8bac3222e07c195f3036b98 Mon Sep 17 00:00:00 2001 From: SnarkAttack Date: Wed, 8 Nov 2023 14:28:27 -0500 Subject: [PATCH 50/74] Add specific badge check to Player --- .../plugins/game_wrapper_pokemon_gen1/core/player.py | 8 ++++++-- .../game_wrapper_pokemon_gen1/data/constants/misc.py | 11 +++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/misc.py diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py index 46d87407a..8fb5dc970 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py @@ -1,5 +1,6 @@ from ..data.memory_addrs.player import PlayerAddresses from ..data.constants.pokemon import PokemonIds +from ..data.constants.misc import Badges class Player: @@ -24,7 +25,7 @@ def load_player(mem_manager): pokemon_in_party = [PokemonIds(mem_manager.read_hex_from_memory(PlayerAddresses.NUM_POKEMON_IN_PARTY[0]+i+1)) for i in range(num_pokemon_in_party)] - badges = mem_manager.read_bitfield_from_memory(PlayerAddresses.BADGES[0]) + badges = mem_manager.read_bitfield_from_memory(PlayerAddresses.BADGES[0], reverse=True) money = mem_manager.read_bcd_from_memory(PlayerAddresses.MONEY[0], PlayerAddresses.MONEY[1]) @@ -36,4 +37,7 @@ def num_pokemon_in_party(self): @property def num_badges(self): - return sum(self._badges) \ No newline at end of file + return sum(self._badges) + + def has_badge(self, badge): + return self._badges[badge] == 1 \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/misc.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/misc.py new file mode 100644 index 000000000..9f0985f46 --- /dev/null +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/misc.py @@ -0,0 +1,11 @@ +from enum import Enum + +class Badges(Enum): + BOULDER_BADGE = 0 + CASCADE_BADGE = 1 + THUNDER_BADGE = 2 + RAINBOW_BADGE = 3 + SOUL_BADGE = 4 + MARSH_BADGE = 5 + VOLCANO_BADGE = 6 + EARTH_BADGE = 7 \ No newline at end of file From f32025b32f48b9f9197906a3832459602a4afe98 Mon Sep 17 00:00:00 2001 From: SnarkAttack Date: Wed, 8 Nov 2023 14:55:41 -0500 Subject: [PATCH 51/74] REname all enums to singular form for better readability --- .../game_wrapper_pokemon_gen1/core/move.py | 4 +- .../game_wrapper_pokemon_gen1/core/player.py | 26 +- .../game_wrapper_pokemon_gen1/core/pokemon.py | 8 +- .../data/constants/items.py | 2 +- .../data/constants/locations.py | 498 +++++++------- .../data/constants/misc.py | 2 +- .../data/constants/moves.py | 2 +- .../data/constants/pokemon.py | 606 +++++++++--------- .../data/constants/sprites.py | 2 +- .../data/constants/status.py | 2 +- .../game_wrapper_pokemon_gen1.py | 1 - 11 files changed, 585 insertions(+), 568 deletions(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/move.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/move.py index 27c90b687..b8af14bae 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/move.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/move.py @@ -1,4 +1,4 @@ -from ..data.constants.moves import MoveIds +from ..data.constants.moves import MoveId class Move(): @@ -13,7 +13,7 @@ def __init__(self, move_id): def get_name_from_id(cls, move_id, camel_case=False): if move_id == 0: return cls.NONEXISTENT_MOVE_STR - move_name = MoveIds(move_id).name.replace('_', ' ') + move_name = MoveId(move_id).name.replace('_', ' ') if camel_case: return move_name.title() return move_name \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py index 8fb5dc970..3c357f450 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py @@ -1,6 +1,6 @@ from ..data.memory_addrs.player import PlayerAddresses -from ..data.constants.pokemon import PokemonIds -from ..data.constants.misc import Badges +from ..data.constants.pokemon import PokemonId +from ..data.constants.misc import Badge class Player: @@ -22,7 +22,7 @@ def load_player(mem_manager): num_pokemon_in_party = mem_manager.read_hex_from_memory(PlayerAddresses.NUM_POKEMON_IN_PARTY[0]) - pokemon_in_party = [PokemonIds(mem_manager.read_hex_from_memory(PlayerAddresses.NUM_POKEMON_IN_PARTY[0]+i+1)) + pokemon_in_party = [PokemonId(mem_manager.read_hex_from_memory(PlayerAddresses.NUM_POKEMON_IN_PARTY[0]+i+1)) for i in range(num_pokemon_in_party)] badges = mem_manager.read_bitfield_from_memory(PlayerAddresses.BADGES[0], reverse=True) @@ -31,6 +31,24 @@ def load_player(mem_manager): return Player(name, pokemon_in_party, badges, money) + @property + def name(self): + return self._name + + @name.setter + def name(self, n): + # Name truncated to 8 characters + self._name = n[:8] + + @property + def money(self): + return self._money + + @money.setter + def money(self, m): + # Max money game can store is 999999 + return max(m, 999999) + @property def num_pokemon_in_party(self): return len(self._pokemon_in_party) @@ -39,5 +57,5 @@ def num_pokemon_in_party(self): def num_badges(self): return sum(self._badges) - def has_badge(self, badge): + def has_badge(self, badge : Badge): return self._badges[badge] == 1 \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py index 4109d1827..a3a42bc9b 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py @@ -1,5 +1,5 @@ from ..data.memory_addrs.pokemon import PokemonBaseAddrs, PokemonMemoryOffsets -from ..data.constants.pokemon import PokemonIds, _POKEMON_NAMES, _POKEMON_POKEDEX_INDEX +from ..data.constants.pokemon import PokemonId, _POKEMON_NAMES, _POKEMON_POKEDEX_INDEX from .move import Move class Pokemon: @@ -36,7 +36,7 @@ def __init__(self, speed=0, special=0, in_party=False): - self.pokemon_id = PokemonIds(pokemon_id) + self.pokemon_id = PokemonId(pokemon_id) self.current_hp = current_hp self.status = status self.type_1 = type_1 @@ -137,11 +137,11 @@ def special(self): @staticmethod def get_pokemon_name_from_id(pokemon_id): - return _POKEMON_NAMES.get(PokemonIds(pokemon_id)) + return _POKEMON_NAMES.get(PokemonId(pokemon_id)) @staticmethod def get_pokedex_id_from_pokemon_id(pokemon_id): - return _POKEMON_POKEDEX_INDEX.get(PokemonIds(pokemon_id)) + return _POKEMON_POKEDEX_INDEX.get(PokemonId(pokemon_id)) @staticmethod diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/items.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/items.py index e0dd897a9..3f79ecc7a 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/items.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/items.py @@ -1,6 +1,6 @@ from enum import Enum -class Items(Enum): +class Item(Enum): MASTER_BALL = 0x01 ULTRA_BALL = 0x02 GREAT_BALL = 0x03 diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/locations.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/locations.py index b2edf900f..b675eaa8f 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/locations.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/locations.py @@ -1,6 +1,6 @@ from enum import Enum -class LocationIds(Enum): +class LocationId(Enum): PALLET_TOWN = 0x00 VIRIDIAN_CITY = 0x01 PEWTER_CITY = 0x02 @@ -251,252 +251,252 @@ class LocationIds(Enum): AGATHAS_ROOM = 0xF7 LOCATION_NAMES = { - LocationIds.PALLET_TOWN: 'PALLET TOWN', - LocationIds.VIRIDIAN_CITY: 'VIRIDIAN CITY', - LocationIds.PEWTER_CITY: 'PEWTER CITY', - LocationIds.CERULEAN_CITY: 'CERULEAN CITY', - LocationIds.LAVENDER_TOWN: 'LAVENDER TOWN', - LocationIds.VERMILION_CITY: 'VERMILION CITY', - LocationIds.CELADON_CITY: 'CELADON CITY', - LocationIds.FUCHSIA_CITY: 'FUCHSIA CITY', - LocationIds.CINNABAR_ISLAND: 'CINNABAR ISLAND', - LocationIds.INDIGO_PLATEAU: 'INDIGO PLATEAU', - LocationIds.SAFFRON_CITY: 'SAFFRON CITY', - LocationIds.UNUSED_MAP_0B: 'UNUSED MAP 0B', - LocationIds.ROUTE_1: 'ROUTE 1', - LocationIds.ROUTE_2: 'ROUTE 2', - LocationIds.ROUTE_3: 'ROUTE 3', - LocationIds.ROUTE_4: 'ROUTE 4', - LocationIds.ROUTE_5: 'ROUTE 5', - LocationIds.ROUTE_6: 'ROUTE 6', - LocationIds.ROUTE_7: 'ROUTE 7', - LocationIds.ROUTE_8: 'ROUTE 8', - LocationIds.ROUTE_9: 'ROUTE 9', - LocationIds.ROUTE_10: 'ROUTE 10', - LocationIds.ROUTE_11: 'ROUTE 11', - LocationIds.ROUTE_12: 'ROUTE 12', - LocationIds.ROUTE_13: 'ROUTE 13', - LocationIds.ROUTE_14: 'ROUTE 14', - LocationIds.ROUTE_15: 'ROUTE 15', - LocationIds.ROUTE_16: 'ROUTE 16', - LocationIds.ROUTE_17: 'ROUTE 17', - LocationIds.ROUTE_18: 'ROUTE 18', - LocationIds.ROUTE_19: 'ROUTE 19', - LocationIds.ROUTE_20: 'ROUTE 20', - LocationIds.ROUTE_21: 'ROUTE 21', - LocationIds.ROUTE_22: 'ROUTE 22', - LocationIds.ROUTE_23: 'ROUTE 23', - LocationIds.ROUTE_24: 'ROUTE 24', - LocationIds.ROUTE_25: 'ROUTE 25', - LocationIds.REDS_HOUSE_1F: 'RED\'S HOUSE 1F', - LocationIds.REDS_HOUSE_2F: 'RED\'S HOUSE 2F', - LocationIds.BLUES_HOUSE: 'BLUE\'S HOUSE', - LocationIds.OAKS_LAB: 'OAK\'S LAB', - LocationIds.VIRIDIAN_POKECENTER: 'VIRIDIAN POKECENTER', - LocationIds.VIRIDIAN_MART: 'VIRIDIAN MART', - LocationIds.VIRIDIAN_SCHOOL_HOUSE: 'VIRIDIAN SCHOOL HOUSE', - LocationIds.VIRIDIAN_NICKNAME_HOUSE: 'VIRIDIAN NICKNAME HOUSE', - LocationIds.VIRIDIAN_GYM: 'VIRIDIAN GYM', - LocationIds.DIGLETTS_CAVE_ROUTE_2: 'DIGLETTS CAVE ROUTE 2', - LocationIds.VIRIDIAN_FOREST_NORTH_GATE: 'VIRIDIAN FOREST NORTH GATE', - LocationIds.ROUTE_2_TRADE_HOUSE: 'ROUTE 2 TRADE HOUSE', - LocationIds.ROUTE_2_GATE: 'ROUTE 2 GATE', - LocationIds.VIRIDIAN_FOREST_SOUTH_GATE: 'VIRIDIAN FOREST SOUTH GATE', - LocationIds.VIRIDIAN_FOREST: 'VIRIDIAN FOREST', - LocationIds.MUSEUM_1F: 'MUSEUM 1F', - LocationIds.MUSEUM_2F: 'MUSEUM 2F', - LocationIds.PEWTER_GYM: 'PEWTER GYM', - LocationIds.PEWTER_NIDORAN_HOUSE: 'PEWTER NIDORAN HOUSE', - LocationIds.PEWTER_MART: 'PEWTER MART', - LocationIds.PEWTER_SPEECH_HOUSE: 'PEWTER SPEECH HOUSE', - LocationIds.PEWTER_POKECENTER: 'PEWTER POKECENTER', - LocationIds.MT_MOON_1F: 'MT MOON 1F', - LocationIds.MT_MOON_B1F: 'MT MOON B1F', - LocationIds.MT_MOON_B2F: 'MT MOON B2F', - LocationIds.CERULEAN_TRASHED_HOUSE: 'CERULEAN TRASHED HOUSE', - LocationIds.CERULEAN_TRADE_HOUSE: 'CERULEAN TRADE HOUSE', - LocationIds.CERULEAN_POKECENTER: 'CERULEAN POKECENTER', - LocationIds.CERULEAN_GYM: 'CERULEAN GYM', - LocationIds.BIKE_SHOP: 'BIKE SHOP', - LocationIds.CERULEAN_MART: 'CERULEAN MART', - LocationIds.MT_MOON_POKECENTER: 'MT MOON POKECENTER', - LocationIds.CERULEAN_TRASHED_HOUSE_COPY: 'CERULEAN TRASHED HOUSE COPY', - LocationIds.ROUTE_5_GATE: 'ROUTE 5 GATE', - LocationIds.UNDERGROUND_PATH_ROUTE_5: 'UNDERGROUND PATH ROUTE 5', - LocationIds.DAYCARE: 'DAYCARE', - LocationIds.ROUTE_6_GATE: 'ROUTE 6 GATE', - LocationIds.UNDERGROUND_PATH_ROUTE_6: 'UNDERGROUND PATH ROUTE 6', - LocationIds.UNDERGROUND_PATH_ROUTE_6_COPY: 'UNDERGROUND PATH ROUTE 6 COPY', - LocationIds.ROUTE_7_GATE: 'ROUTE 7 GATE', - LocationIds.UNDERGROUND_PATH_ROUTE_7: 'UNDERGROUND PATH ROUTE 7', - LocationIds.UNDERGROUND_PATH_ROUTE_7_COPY: 'UNDERGROUND PATH ROUTE 7 COPY', - LocationIds.ROUTE_8_GATE: 'ROUTE 8 GATE', - LocationIds.UNDERGROUND_PATH_ROUTE_8: 'UNDERGROUND PATH ROUTE 8', - LocationIds.ROCK_TUNNEL_POKECENTER: 'ROCK TUNNEL POKECENTER', - LocationIds.ROCK_TUNNEL_1F: 'ROCK TUNNEL 1F', - LocationIds.POWER_PLANT: 'POWER PLANT', - LocationIds.ROUTE_11_GATE_1F: 'ROUTE 11 GATE 1F', - LocationIds.DIGLETTS_CAVE_ROUTE_11: 'DIGLETT\'S CAVE ROUTE 11', - LocationIds.ROUTE_11_GATE_2F: 'ROUTE 11 GATE 2F', - LocationIds.ROUTE_12_GATE_1F: 'ROUTE 12 GATE 1F', - LocationIds.BILLS_HOUSE: 'BILLS HOUSE', - LocationIds.VERMILION_POKECENTER: 'VERMILION POKECENTER', - LocationIds.POKEMON_FAN_CLUB: 'POKEMON FAN CLUB', - LocationIds.VERMILION_MART: 'VERMILION MART', - LocationIds.VERMILION_GYM: 'VERMILION GYM', - LocationIds.VERMILION_PIDGEY_HOUSE: 'VERMILION PIDGEY HOUSE', - LocationIds.VERMILION_DOCK: 'VERMILION DOCK', - LocationIds.SS_ANNE_1F: 'SS ANNE 1F', - LocationIds.SS_ANNE_2F: 'SS ANNE 2F', - LocationIds.SS_ANNE_3F: 'SS ANNE 3F', - LocationIds.SS_ANNE_B1F: 'SS ANNE B1F', - LocationIds.SS_ANNE_BOW: 'SS ANNE BOW', - LocationIds.SS_ANNE_KITCHEN: 'SS ANNE KITCHEN', - LocationIds.SS_ANNE_CAPTAINS_ROOM: 'SS ANNE CAPTAIN\'S ROOM', - LocationIds.SS_ANNE_1F_ROOMS: 'SS ANNE 1F ROOMS', - LocationIds.SS_ANNE_2F_ROOMS: 'SS ANNE 2F ROOMS', - LocationIds.SS_ANNE_B1F_ROOMS: 'SS ANNE B1F ROOMS', - LocationIds.UNUSED_MAP_69: 'UNUSED MAP 69', - LocationIds.UNUSED_MAP_6A: 'UNUSED MAP 6A', - LocationIds.UNUSED_MAP_6B: 'UNUSED MAP 6B', - LocationIds.VICTORY_ROAD_1F: 'VICTORY ROAD 1F', - LocationIds.UNUSED_MAP_6D: 'UNUSED MAP 6D', - LocationIds.UNUSED_MAP_6E: 'UNUSED MAP 6E', - LocationIds.UNUSED_MAP_6F: 'UNUSED MAP 6F', - LocationIds.UNUSED_MAP_70: 'UNUSED MAP 70', - LocationIds.LANCES_ROOM: 'LANCES ROOM', - LocationIds.UNUSED_MAP_72: 'UNUSED MAP 72', - LocationIds.UNUSED_MAP_73: 'UNUSED MAP 73', - LocationIds.UNUSED_MAP_74: 'UNUSED MAP 74', - LocationIds.UNUSED_MAP_75: 'UNUSED MAP 75', - LocationIds.HALL_OF_FAME: 'HALL OF FAME', - LocationIds.UNDERGROUND_PATH_NORTH_SOUTH: 'UNDERGROUND PATH NORTH SOUTH', - LocationIds.CHAMPIONS_ROOM: 'CHAMPION\'S ROOM', - LocationIds.UNDERGROUND_PATH_WEST_EAST: 'UNDERGROUND PATH WEST EAST', - LocationIds.CELADON_MART_1F: 'CELADON MART 1F', - LocationIds.CELADON_MART_2F: 'CELADON MART 2F', - LocationIds.CELADON_MART_3F: 'CELADON MART 3F', - LocationIds.CELADON_MART_4F: 'CELADON MART 4F', - LocationIds.CELADON_MART_ROOF: 'CELADON MART ROOF', - LocationIds.CELADON_MART_ELEVATOR: 'CELADON MART ELEVATOR', - LocationIds.CELADON_MANSION_1F: 'CELADON MANSION 1F', - LocationIds.CELADON_MANSION_2F: 'CELADON MANSION 2F', - LocationIds.CELADON_MANSION_3F: 'CELADON MANSION 3F', - LocationIds.CELADON_MANSION_ROOF: 'CELADON MANSION ROOF', - LocationIds.CELADON_MANSION_ROOF_HOUSE: 'CELADON MANSION ROOF HOUSE', - LocationIds.CELADON_POKECENTER: 'CELADON POKECENTER', - LocationIds.CELADON_GYM: 'CELADON GYM', - LocationIds.GAME_CORNER: 'GAME CORNER', - LocationIds.CELADON_MART_5F: 'CELADON MART 5F', - LocationIds.GAME_CORNER_PRIZE_ROOM: 'GAME CORNER PRIZE ROOM', - LocationIds.CELADON_DINER: 'CELADON DINER', - LocationIds.CELADON_CHIEF_HOUSE: 'CELADON CHIEF HOUSE', - LocationIds.CELADON_HOTEL: 'CELADON HOTEL', - LocationIds.LAVENDER_POKECENTER: 'LAVENDER POKECENTER', - LocationIds.POKEMON_TOWER_1F: 'POKEMON TOWER 1F', - LocationIds.POKEMON_TOWER_2F: 'POKEMON TOWER 2F', - LocationIds.POKEMON_TOWER_3F: 'POKEMON TOWER 3F', - LocationIds.POKEMON_TOWER_4F: 'POKEMON TOWER 4F', - LocationIds.POKEMON_TOWER_5F: 'POKEMON TOWER 5F', - LocationIds.POKEMON_TOWER_6F: 'POKEMON TOWER 6F', - LocationIds.POKEMON_TOWER_7F: 'POKEMON TOWER 7F', - LocationIds.MR_FUJIS_HOUSE: 'MR FUJIS HOUSE', - LocationIds.LAVENDER_MART: 'LAVENDER MART', - LocationIds.LAVENDER_CUBONE_HOUSE: 'LAVENDER CUBONE HOUSE', - LocationIds.FUCHSIA_MART: 'FUCHSIA MART', - LocationIds.FUCHSIA_BILLS_GRANDPAS_HOUSE: 'FUCHSIA BILL\'S GRANDPAS HOUSE', - LocationIds.FUCHSIA_POKECENTER: 'FUCHSIA POKECENTER', - LocationIds.WARDENS_HOUSE: 'WARDENS HOUSE', - LocationIds.SAFARI_ZONE_GATE: 'SAFARI ZONE GATE', - LocationIds.FUCHSIA_GYM: 'FUCHSIA GYM', - LocationIds.FUCHSIA_MEETING_ROOM: 'FUCHSIA MEETING ROOM', - LocationIds.SEAFOAM_ISLANDS_B1F: 'SEAFOAM ISLANDS B1F', - LocationIds.SEAFOAM_ISLANDS_B2F: 'SEAFOAM ISLANDS B2F', - LocationIds.SEAFOAM_ISLANDS_B3F: 'SEAFOAM ISLANDS B3F', - LocationIds.SEAFOAM_ISLANDS_B4F: 'SEAFOAM ISLANDS B4F', - LocationIds.VERMILION_OLD_ROD_HOUSE: 'VERMILION OLD ROD HOUSE', - LocationIds.FUCHSIA_GOOD_ROD_HOUSE: 'FUCHSIA GOOD ROD HOUSE', - LocationIds.POKEMON_MANSION_1F: 'POKEMON MANSION 1F', - LocationIds.CINNABAR_GYM: 'CINNABAR GYM', - LocationIds.CINNABAR_LAB: 'CINNABAR LAB', - LocationIds.CINNABAR_LAB_TRADE_ROOM: 'CINNABAR LAB TRADE ROOM', - LocationIds.CINNABAR_LAB_METRONOME_ROOM: 'CINNABAR LAB METRONOME ROOM', - LocationIds.CINNABAR_LAB_FOSSIL_ROOM: 'CINNABAR LAB FOSSIL ROOM', - LocationIds.CINNABAR_POKECENTER: 'CINNABAR POKECENTER', - LocationIds.CINNABAR_MART: 'CINNABAR MART', - LocationIds.CINNABAR_MART_COPY: 'CINNABAR MART COPY', - LocationIds.INDIGO_PLATEAU_LOBBY: 'INDIGO PLATEAU LOBBY', - LocationIds.COPYCATS_HOUSE_1F: 'COPYCATS HOUSE 1F', - LocationIds.COPYCATS_HOUSE_2F: 'COPYCATS HOUSE 2F', - LocationIds.FIGHTING_DOJO: 'FIGHTING DOJO', - LocationIds.SAFFRON_GYM: 'SAFFRON GYM', - LocationIds.SAFFRON_PIDGEY_HOUSE: 'SAFFRON PIDGEY HOUSE', - LocationIds.SAFFRON_MART: 'SAFFRON MART', - LocationIds.SILPH_CO_1F: 'SILPH CO 1F', - LocationIds.SAFFRON_POKECENTER: 'SAFFRON POKECENTER', - LocationIds.MR_PSYCHICS_HOUSE: 'MR PSYCHICS HOUSE', - LocationIds.ROUTE_15_GATE_1F: 'ROUTE 15 GATE 1F', - LocationIds.ROUTE_15_GATE_2F: 'ROUTE 15 GATE 2F', - LocationIds.ROUTE_16_GATE_1F: 'ROUTE 16 GATE 1F', - LocationIds.ROUTE_16_GATE_2F: 'ROUTE 16 GATE 2F', - LocationIds.ROUTE_16_FLY_HOUSE: 'ROUTE 16 FLY HOUSE', - LocationIds.ROUTE_12_SUPER_ROD_HOUSE: 'ROUTE 12 SUPER ROD HOUSE', - LocationIds.ROUTE_18_GATE_1F: 'ROUTE 18 GATE 1F', - LocationIds.ROUTE_18_GATE_2F: 'ROUTE 18 GATE 2F', - LocationIds.SEAFOAM_ISLANDS_1F: 'SEAFOAM ISLANDS 1F', - LocationIds.ROUTE_22_GATE: 'ROUTE 22 GATE', - LocationIds.VICTORY_ROAD_2F: 'VICTORY ROAD 2F', - LocationIds.ROUTE_12_GATE_2F: 'ROUTE 12 GATE 2F', - LocationIds.VERMILION_TRADE_HOUSE: 'VERMILION TRADE HOUSE', - LocationIds.DIGLETTS_CAVE: 'DIGLETTS CAVE', - LocationIds.VICTORY_ROAD_3F: 'VICTORY ROAD 3F', - LocationIds.ROCKET_HIDEOUT_B1F: 'ROCKET HIDEOUT B1F', - LocationIds.ROCKET_HIDEOUT_B2F: 'ROCKET HIDEOUT B2F', - LocationIds.ROCKET_HIDEOUT_B3F: 'ROCKET HIDEOUT B3F', - LocationIds.ROCKET_HIDEOUT_B4F: 'ROCKET HIDEOUT B4F', - LocationIds.ROCKET_HIDEOUT_ELEVATOR: 'ROCKET HIDEOUT ELEVATOR', - LocationIds.UNUSED_MAP_CC: 'UNUSED MAP CC', - LocationIds.UNUSED_MAP_CD: 'UNUSED MAP CD', - LocationIds.UNUSED_MAP_CE: 'UNUSED MAP CE', - LocationIds.SILPH_CO_2F: 'SILPH CO 2F', - LocationIds.SILPH_CO_3F: 'SILPH CO 3F', - LocationIds.SILPH_CO_4F: 'SILPH CO 4F', - LocationIds.SILPH_CO_5F: 'SILPH CO 5F', - LocationIds.SILPH_CO_6F: 'SILPH CO 6F', - LocationIds.SILPH_CO_7F: 'SILPH CO 7F', - LocationIds.SILPH_CO_8F: 'SILPH CO 8F', - LocationIds.POKEMON_MANSION_2F: 'POKEMON MANSION 2F', - LocationIds.POKEMON_MANSION_3F: 'POKEMON MANSION 3F', - LocationIds.POKEMON_MANSION_B1F: 'POKEMON MANSION B1F', - LocationIds.SAFARI_ZONE_EAST: 'SAFARI ZONE EAST', - LocationIds.SAFARI_ZONE_NORTH: 'SAFARI ZONE NORTH', - LocationIds.SAFARI_ZONE_WEST: 'SAFARI ZONE WEST', - LocationIds.SAFARI_ZONE_CENTER: 'SAFARI ZONE CENTER', - LocationIds.SAFARI_ZONE_CENTER_REST_HOUSE: 'SAFARI ZONE CENTER REST HOUSE', - LocationIds.SAFARI_ZONE_SECRET_HOUSE: 'SAFARI ZONE SECRET HOUSE', - LocationIds.SAFARI_ZONE_WEST_REST_HOUSE: 'SAFARI ZONE WEST REST HOUSE', - LocationIds.SAFARI_ZONE_EAST_REST_HOUSE: 'SAFARI ZONE EAST REST HOUSE', - LocationIds.SAFARI_ZONE_NORTH_REST_HOUSE: 'SAFARI ZONE NORTH REST HOUSE', - LocationIds.CERULEAN_CAVE_2F: 'CERULEAN CAVE 2F', - LocationIds.CERULEAN_CAVE_B1F: 'CERULEAN CAVE B1F', - LocationIds.CERULEAN_CAVE_1F: 'CERULEAN CAVE 1F', - LocationIds.NAME_RATERS_HOUSE: 'NAME RATER\'S HOUSE', - LocationIds.CERULEAN_BADGE_HOUSE: 'CERULEAN BADGE HOUSE', - LocationIds.UNUSED_MAP_E7: 'UNUSED MAP E7', - LocationIds.ROCK_TUNNEL_B1F: 'ROCK TUNNEL B1F', - LocationIds.SILPH_CO_9F: 'SILPH CO 9F', - LocationIds.SILPH_CO_10F: 'SILPH CO 10F', - LocationIds.SILPH_CO_11F: 'SILPH CO 11F', - LocationIds.SILPH_CO_ELEVATOR: 'SILPH CO ELEVATOR', - LocationIds.UNUSED_MAP_ED: 'UNUSED MAP ED', - LocationIds.UNUSED_MAP_EE: 'UNUSED MAP EE', - LocationIds.TRADE_CENTER: 'TRADE CENTER', - LocationIds.COLOSSEUM: 'COLOSSEUM', - LocationIds.UNUSED_MAP_F1: 'UNUSED MAP F1', - LocationIds.UNUSED_MAP_F2: 'UNUSED MAP F2', - LocationIds.UNUSED_MAP_F3: 'UNUSED MAP F3', - LocationIds.UNUSED_MAP_F4: 'UNUSED MAP F4', - LocationIds.LORELEIS_ROOM: 'LORELEI\'S ROOM', - LocationIds.BRUNOS_ROOM: 'BRUNO\'S ROOM', - LocationIds.AGATHAS_ROOM: 'AGATHA\'S ROOM', + LocationId.PALLET_TOWN: 'PALLET TOWN', + LocationId.VIRIDIAN_CITY: 'VIRIDIAN CITY', + LocationId.PEWTER_CITY: 'PEWTER CITY', + LocationId.CERULEAN_CITY: 'CERULEAN CITY', + LocationId.LAVENDER_TOWN: 'LAVENDER TOWN', + LocationId.VERMILION_CITY: 'VERMILION CITY', + LocationId.CELADON_CITY: 'CELADON CITY', + LocationId.FUCHSIA_CITY: 'FUCHSIA CITY', + LocationId.CINNABAR_ISLAND: 'CINNABAR ISLAND', + LocationId.INDIGO_PLATEAU: 'INDIGO PLATEAU', + LocationId.SAFFRON_CITY: 'SAFFRON CITY', + LocationId.UNUSED_MAP_0B: 'UNUSED MAP 0B', + LocationId.ROUTE_1: 'ROUTE 1', + LocationId.ROUTE_2: 'ROUTE 2', + LocationId.ROUTE_3: 'ROUTE 3', + LocationId.ROUTE_4: 'ROUTE 4', + LocationId.ROUTE_5: 'ROUTE 5', + LocationId.ROUTE_6: 'ROUTE 6', + LocationId.ROUTE_7: 'ROUTE 7', + LocationId.ROUTE_8: 'ROUTE 8', + LocationId.ROUTE_9: 'ROUTE 9', + LocationId.ROUTE_10: 'ROUTE 10', + LocationId.ROUTE_11: 'ROUTE 11', + LocationId.ROUTE_12: 'ROUTE 12', + LocationId.ROUTE_13: 'ROUTE 13', + LocationId.ROUTE_14: 'ROUTE 14', + LocationId.ROUTE_15: 'ROUTE 15', + LocationId.ROUTE_16: 'ROUTE 16', + LocationId.ROUTE_17: 'ROUTE 17', + LocationId.ROUTE_18: 'ROUTE 18', + LocationId.ROUTE_19: 'ROUTE 19', + LocationId.ROUTE_20: 'ROUTE 20', + LocationId.ROUTE_21: 'ROUTE 21', + LocationId.ROUTE_22: 'ROUTE 22', + LocationId.ROUTE_23: 'ROUTE 23', + LocationId.ROUTE_24: 'ROUTE 24', + LocationId.ROUTE_25: 'ROUTE 25', + LocationId.REDS_HOUSE_1F: 'RED\'S HOUSE 1F', + LocationId.REDS_HOUSE_2F: 'RED\'S HOUSE 2F', + LocationId.BLUES_HOUSE: 'BLUE\'S HOUSE', + LocationId.OAKS_LAB: 'OAK\'S LAB', + LocationId.VIRIDIAN_POKECENTER: 'VIRIDIAN POKECENTER', + LocationId.VIRIDIAN_MART: 'VIRIDIAN MART', + LocationId.VIRIDIAN_SCHOOL_HOUSE: 'VIRIDIAN SCHOOL HOUSE', + LocationId.VIRIDIAN_NICKNAME_HOUSE: 'VIRIDIAN NICKNAME HOUSE', + LocationId.VIRIDIAN_GYM: 'VIRIDIAN GYM', + LocationId.DIGLETTS_CAVE_ROUTE_2: 'DIGLETTS CAVE ROUTE 2', + LocationId.VIRIDIAN_FOREST_NORTH_GATE: 'VIRIDIAN FOREST NORTH GATE', + LocationId.ROUTE_2_TRADE_HOUSE: 'ROUTE 2 TRADE HOUSE', + LocationId.ROUTE_2_GATE: 'ROUTE 2 GATE', + LocationId.VIRIDIAN_FOREST_SOUTH_GATE: 'VIRIDIAN FOREST SOUTH GATE', + LocationId.VIRIDIAN_FOREST: 'VIRIDIAN FOREST', + LocationId.MUSEUM_1F: 'MUSEUM 1F', + LocationId.MUSEUM_2F: 'MUSEUM 2F', + LocationId.PEWTER_GYM: 'PEWTER GYM', + LocationId.PEWTER_NIDORAN_HOUSE: 'PEWTER NIDORAN HOUSE', + LocationId.PEWTER_MART: 'PEWTER MART', + LocationId.PEWTER_SPEECH_HOUSE: 'PEWTER SPEECH HOUSE', + LocationId.PEWTER_POKECENTER: 'PEWTER POKECENTER', + LocationId.MT_MOON_1F: 'MT MOON 1F', + LocationId.MT_MOON_B1F: 'MT MOON B1F', + LocationId.MT_MOON_B2F: 'MT MOON B2F', + LocationId.CERULEAN_TRASHED_HOUSE: 'CERULEAN TRASHED HOUSE', + LocationId.CERULEAN_TRADE_HOUSE: 'CERULEAN TRADE HOUSE', + LocationId.CERULEAN_POKECENTER: 'CERULEAN POKECENTER', + LocationId.CERULEAN_GYM: 'CERULEAN GYM', + LocationId.BIKE_SHOP: 'BIKE SHOP', + LocationId.CERULEAN_MART: 'CERULEAN MART', + LocationId.MT_MOON_POKECENTER: 'MT MOON POKECENTER', + LocationId.CERULEAN_TRASHED_HOUSE_COPY: 'CERULEAN TRASHED HOUSE COPY', + LocationId.ROUTE_5_GATE: 'ROUTE 5 GATE', + LocationId.UNDERGROUND_PATH_ROUTE_5: 'UNDERGROUND PATH ROUTE 5', + LocationId.DAYCARE: 'DAYCARE', + LocationId.ROUTE_6_GATE: 'ROUTE 6 GATE', + LocationId.UNDERGROUND_PATH_ROUTE_6: 'UNDERGROUND PATH ROUTE 6', + LocationId.UNDERGROUND_PATH_ROUTE_6_COPY: 'UNDERGROUND PATH ROUTE 6 COPY', + LocationId.ROUTE_7_GATE: 'ROUTE 7 GATE', + LocationId.UNDERGROUND_PATH_ROUTE_7: 'UNDERGROUND PATH ROUTE 7', + LocationId.UNDERGROUND_PATH_ROUTE_7_COPY: 'UNDERGROUND PATH ROUTE 7 COPY', + LocationId.ROUTE_8_GATE: 'ROUTE 8 GATE', + LocationId.UNDERGROUND_PATH_ROUTE_8: 'UNDERGROUND PATH ROUTE 8', + LocationId.ROCK_TUNNEL_POKECENTER: 'ROCK TUNNEL POKECENTER', + LocationId.ROCK_TUNNEL_1F: 'ROCK TUNNEL 1F', + LocationId.POWER_PLANT: 'POWER PLANT', + LocationId.ROUTE_11_GATE_1F: 'ROUTE 11 GATE 1F', + LocationId.DIGLETTS_CAVE_ROUTE_11: 'DIGLETT\'S CAVE ROUTE 11', + LocationId.ROUTE_11_GATE_2F: 'ROUTE 11 GATE 2F', + LocationId.ROUTE_12_GATE_1F: 'ROUTE 12 GATE 1F', + LocationId.BILLS_HOUSE: 'BILLS HOUSE', + LocationId.VERMILION_POKECENTER: 'VERMILION POKECENTER', + LocationId.POKEMON_FAN_CLUB: 'POKEMON FAN CLUB', + LocationId.VERMILION_MART: 'VERMILION MART', + LocationId.VERMILION_GYM: 'VERMILION GYM', + LocationId.VERMILION_PIDGEY_HOUSE: 'VERMILION PIDGEY HOUSE', + LocationId.VERMILION_DOCK: 'VERMILION DOCK', + LocationId.SS_ANNE_1F: 'SS ANNE 1F', + LocationId.SS_ANNE_2F: 'SS ANNE 2F', + LocationId.SS_ANNE_3F: 'SS ANNE 3F', + LocationId.SS_ANNE_B1F: 'SS ANNE B1F', + LocationId.SS_ANNE_BOW: 'SS ANNE BOW', + LocationId.SS_ANNE_KITCHEN: 'SS ANNE KITCHEN', + LocationId.SS_ANNE_CAPTAINS_ROOM: 'SS ANNE CAPTAIN\'S ROOM', + LocationId.SS_ANNE_1F_ROOMS: 'SS ANNE 1F ROOMS', + LocationId.SS_ANNE_2F_ROOMS: 'SS ANNE 2F ROOMS', + LocationId.SS_ANNE_B1F_ROOMS: 'SS ANNE B1F ROOMS', + LocationId.UNUSED_MAP_69: 'UNUSED MAP 69', + LocationId.UNUSED_MAP_6A: 'UNUSED MAP 6A', + LocationId.UNUSED_MAP_6B: 'UNUSED MAP 6B', + LocationId.VICTORY_ROAD_1F: 'VICTORY ROAD 1F', + LocationId.UNUSED_MAP_6D: 'UNUSED MAP 6D', + LocationId.UNUSED_MAP_6E: 'UNUSED MAP 6E', + LocationId.UNUSED_MAP_6F: 'UNUSED MAP 6F', + LocationId.UNUSED_MAP_70: 'UNUSED MAP 70', + LocationId.LANCES_ROOM: 'LANCES ROOM', + LocationId.UNUSED_MAP_72: 'UNUSED MAP 72', + LocationId.UNUSED_MAP_73: 'UNUSED MAP 73', + LocationId.UNUSED_MAP_74: 'UNUSED MAP 74', + LocationId.UNUSED_MAP_75: 'UNUSED MAP 75', + LocationId.HALL_OF_FAME: 'HALL OF FAME', + LocationId.UNDERGROUND_PATH_NORTH_SOUTH: 'UNDERGROUND PATH NORTH SOUTH', + LocationId.CHAMPIONS_ROOM: 'CHAMPION\'S ROOM', + LocationId.UNDERGROUND_PATH_WEST_EAST: 'UNDERGROUND PATH WEST EAST', + LocationId.CELADON_MART_1F: 'CELADON MART 1F', + LocationId.CELADON_MART_2F: 'CELADON MART 2F', + LocationId.CELADON_MART_3F: 'CELADON MART 3F', + LocationId.CELADON_MART_4F: 'CELADON MART 4F', + LocationId.CELADON_MART_ROOF: 'CELADON MART ROOF', + LocationId.CELADON_MART_ELEVATOR: 'CELADON MART ELEVATOR', + LocationId.CELADON_MANSION_1F: 'CELADON MANSION 1F', + LocationId.CELADON_MANSION_2F: 'CELADON MANSION 2F', + LocationId.CELADON_MANSION_3F: 'CELADON MANSION 3F', + LocationId.CELADON_MANSION_ROOF: 'CELADON MANSION ROOF', + LocationId.CELADON_MANSION_ROOF_HOUSE: 'CELADON MANSION ROOF HOUSE', + LocationId.CELADON_POKECENTER: 'CELADON POKECENTER', + LocationId.CELADON_GYM: 'CELADON GYM', + LocationId.GAME_CORNER: 'GAME CORNER', + LocationId.CELADON_MART_5F: 'CELADON MART 5F', + LocationId.GAME_CORNER_PRIZE_ROOM: 'GAME CORNER PRIZE ROOM', + LocationId.CELADON_DINER: 'CELADON DINER', + LocationId.CELADON_CHIEF_HOUSE: 'CELADON CHIEF HOUSE', + LocationId.CELADON_HOTEL: 'CELADON HOTEL', + LocationId.LAVENDER_POKECENTER: 'LAVENDER POKECENTER', + LocationId.POKEMON_TOWER_1F: 'POKEMON TOWER 1F', + LocationId.POKEMON_TOWER_2F: 'POKEMON TOWER 2F', + LocationId.POKEMON_TOWER_3F: 'POKEMON TOWER 3F', + LocationId.POKEMON_TOWER_4F: 'POKEMON TOWER 4F', + LocationId.POKEMON_TOWER_5F: 'POKEMON TOWER 5F', + LocationId.POKEMON_TOWER_6F: 'POKEMON TOWER 6F', + LocationId.POKEMON_TOWER_7F: 'POKEMON TOWER 7F', + LocationId.MR_FUJIS_HOUSE: 'MR FUJIS HOUSE', + LocationId.LAVENDER_MART: 'LAVENDER MART', + LocationId.LAVENDER_CUBONE_HOUSE: 'LAVENDER CUBONE HOUSE', + LocationId.FUCHSIA_MART: 'FUCHSIA MART', + LocationId.FUCHSIA_BILLS_GRANDPAS_HOUSE: 'FUCHSIA BILL\'S GRANDPAS HOUSE', + LocationId.FUCHSIA_POKECENTER: 'FUCHSIA POKECENTER', + LocationId.WARDENS_HOUSE: 'WARDENS HOUSE', + LocationId.SAFARI_ZONE_GATE: 'SAFARI ZONE GATE', + LocationId.FUCHSIA_GYM: 'FUCHSIA GYM', + LocationId.FUCHSIA_MEETING_ROOM: 'FUCHSIA MEETING ROOM', + LocationId.SEAFOAM_ISLANDS_B1F: 'SEAFOAM ISLANDS B1F', + LocationId.SEAFOAM_ISLANDS_B2F: 'SEAFOAM ISLANDS B2F', + LocationId.SEAFOAM_ISLANDS_B3F: 'SEAFOAM ISLANDS B3F', + LocationId.SEAFOAM_ISLANDS_B4F: 'SEAFOAM ISLANDS B4F', + LocationId.VERMILION_OLD_ROD_HOUSE: 'VERMILION OLD ROD HOUSE', + LocationId.FUCHSIA_GOOD_ROD_HOUSE: 'FUCHSIA GOOD ROD HOUSE', + LocationId.POKEMON_MANSION_1F: 'POKEMON MANSION 1F', + LocationId.CINNABAR_GYM: 'CINNABAR GYM', + LocationId.CINNABAR_LAB: 'CINNABAR LAB', + LocationId.CINNABAR_LAB_TRADE_ROOM: 'CINNABAR LAB TRADE ROOM', + LocationId.CINNABAR_LAB_METRONOME_ROOM: 'CINNABAR LAB METRONOME ROOM', + LocationId.CINNABAR_LAB_FOSSIL_ROOM: 'CINNABAR LAB FOSSIL ROOM', + LocationId.CINNABAR_POKECENTER: 'CINNABAR POKECENTER', + LocationId.CINNABAR_MART: 'CINNABAR MART', + LocationId.CINNABAR_MART_COPY: 'CINNABAR MART COPY', + LocationId.INDIGO_PLATEAU_LOBBY: 'INDIGO PLATEAU LOBBY', + LocationId.COPYCATS_HOUSE_1F: 'COPYCATS HOUSE 1F', + LocationId.COPYCATS_HOUSE_2F: 'COPYCATS HOUSE 2F', + LocationId.FIGHTING_DOJO: 'FIGHTING DOJO', + LocationId.SAFFRON_GYM: 'SAFFRON GYM', + LocationId.SAFFRON_PIDGEY_HOUSE: 'SAFFRON PIDGEY HOUSE', + LocationId.SAFFRON_MART: 'SAFFRON MART', + LocationId.SILPH_CO_1F: 'SILPH CO 1F', + LocationId.SAFFRON_POKECENTER: 'SAFFRON POKECENTER', + LocationId.MR_PSYCHICS_HOUSE: 'MR PSYCHICS HOUSE', + LocationId.ROUTE_15_GATE_1F: 'ROUTE 15 GATE 1F', + LocationId.ROUTE_15_GATE_2F: 'ROUTE 15 GATE 2F', + LocationId.ROUTE_16_GATE_1F: 'ROUTE 16 GATE 1F', + LocationId.ROUTE_16_GATE_2F: 'ROUTE 16 GATE 2F', + LocationId.ROUTE_16_FLY_HOUSE: 'ROUTE 16 FLY HOUSE', + LocationId.ROUTE_12_SUPER_ROD_HOUSE: 'ROUTE 12 SUPER ROD HOUSE', + LocationId.ROUTE_18_GATE_1F: 'ROUTE 18 GATE 1F', + LocationId.ROUTE_18_GATE_2F: 'ROUTE 18 GATE 2F', + LocationId.SEAFOAM_ISLANDS_1F: 'SEAFOAM ISLANDS 1F', + LocationId.ROUTE_22_GATE: 'ROUTE 22 GATE', + LocationId.VICTORY_ROAD_2F: 'VICTORY ROAD 2F', + LocationId.ROUTE_12_GATE_2F: 'ROUTE 12 GATE 2F', + LocationId.VERMILION_TRADE_HOUSE: 'VERMILION TRADE HOUSE', + LocationId.DIGLETTS_CAVE: 'DIGLETTS CAVE', + LocationId.VICTORY_ROAD_3F: 'VICTORY ROAD 3F', + LocationId.ROCKET_HIDEOUT_B1F: 'ROCKET HIDEOUT B1F', + LocationId.ROCKET_HIDEOUT_B2F: 'ROCKET HIDEOUT B2F', + LocationId.ROCKET_HIDEOUT_B3F: 'ROCKET HIDEOUT B3F', + LocationId.ROCKET_HIDEOUT_B4F: 'ROCKET HIDEOUT B4F', + LocationId.ROCKET_HIDEOUT_ELEVATOR: 'ROCKET HIDEOUT ELEVATOR', + LocationId.UNUSED_MAP_CC: 'UNUSED MAP CC', + LocationId.UNUSED_MAP_CD: 'UNUSED MAP CD', + LocationId.UNUSED_MAP_CE: 'UNUSED MAP CE', + LocationId.SILPH_CO_2F: 'SILPH CO 2F', + LocationId.SILPH_CO_3F: 'SILPH CO 3F', + LocationId.SILPH_CO_4F: 'SILPH CO 4F', + LocationId.SILPH_CO_5F: 'SILPH CO 5F', + LocationId.SILPH_CO_6F: 'SILPH CO 6F', + LocationId.SILPH_CO_7F: 'SILPH CO 7F', + LocationId.SILPH_CO_8F: 'SILPH CO 8F', + LocationId.POKEMON_MANSION_2F: 'POKEMON MANSION 2F', + LocationId.POKEMON_MANSION_3F: 'POKEMON MANSION 3F', + LocationId.POKEMON_MANSION_B1F: 'POKEMON MANSION B1F', + LocationId.SAFARI_ZONE_EAST: 'SAFARI ZONE EAST', + LocationId.SAFARI_ZONE_NORTH: 'SAFARI ZONE NORTH', + LocationId.SAFARI_ZONE_WEST: 'SAFARI ZONE WEST', + LocationId.SAFARI_ZONE_CENTER: 'SAFARI ZONE CENTER', + LocationId.SAFARI_ZONE_CENTER_REST_HOUSE: 'SAFARI ZONE CENTER REST HOUSE', + LocationId.SAFARI_ZONE_SECRET_HOUSE: 'SAFARI ZONE SECRET HOUSE', + LocationId.SAFARI_ZONE_WEST_REST_HOUSE: 'SAFARI ZONE WEST REST HOUSE', + LocationId.SAFARI_ZONE_EAST_REST_HOUSE: 'SAFARI ZONE EAST REST HOUSE', + LocationId.SAFARI_ZONE_NORTH_REST_HOUSE: 'SAFARI ZONE NORTH REST HOUSE', + LocationId.CERULEAN_CAVE_2F: 'CERULEAN CAVE 2F', + LocationId.CERULEAN_CAVE_B1F: 'CERULEAN CAVE B1F', + LocationId.CERULEAN_CAVE_1F: 'CERULEAN CAVE 1F', + LocationId.NAME_RATERS_HOUSE: 'NAME RATER\'S HOUSE', + LocationId.CERULEAN_BADGE_HOUSE: 'CERULEAN BADGE HOUSE', + LocationId.UNUSED_MAP_E7: 'UNUSED MAP E7', + LocationId.ROCK_TUNNEL_B1F: 'ROCK TUNNEL B1F', + LocationId.SILPH_CO_9F: 'SILPH CO 9F', + LocationId.SILPH_CO_10F: 'SILPH CO 10F', + LocationId.SILPH_CO_11F: 'SILPH CO 11F', + LocationId.SILPH_CO_ELEVATOR: 'SILPH CO ELEVATOR', + LocationId.UNUSED_MAP_ED: 'UNUSED MAP ED', + LocationId.UNUSED_MAP_EE: 'UNUSED MAP EE', + LocationId.TRADE_CENTER: 'TRADE CENTER', + LocationId.COLOSSEUM: 'COLOSSEUM', + LocationId.UNUSED_MAP_F1: 'UNUSED MAP F1', + LocationId.UNUSED_MAP_F2: 'UNUSED MAP F2', + LocationId.UNUSED_MAP_F3: 'UNUSED MAP F3', + LocationId.UNUSED_MAP_F4: 'UNUSED MAP F4', + LocationId.LORELEIS_ROOM: 'LORELEI\'S ROOM', + LocationId.BRUNOS_ROOM: 'BRUNO\'S ROOM', + LocationId.AGATHAS_ROOM: 'AGATHA\'S ROOM', } \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/misc.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/misc.py index 9f0985f46..906daebe3 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/misc.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/misc.py @@ -1,6 +1,6 @@ from enum import Enum -class Badges(Enum): +class Badge(Enum): BOULDER_BADGE = 0 CASCADE_BADGE = 1 THUNDER_BADGE = 2 diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/moves.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/moves.py index da7860ad9..4bf21950b 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/moves.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/moves.py @@ -1,6 +1,6 @@ from enum import Enum -class MoveIds(Enum): +class MoveId(Enum): POUND = 0x01 KARATE_CHOP = 0x02 DOUBLESLAP = 0x03 diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/pokemon.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/pokemon.py index 76397dabe..52fa079d0 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/pokemon.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/pokemon.py @@ -1,6 +1,6 @@ from enum import Enum -class PokemonIds(Enum): +class PokemonId(Enum): RHYDON = 0x01 KANGASKHAN = 0x02 NIDORAN_M = 0x03 @@ -193,309 +193,309 @@ class PokemonIds(Enum): VICTREEBEL = 0xBE _POKEMON_POKEDEX_INDEX = { - PokemonIds.BULBASAUR: 1, - PokemonIds.IVYSAUR: 2, - PokemonIds.VENUSAUR: 3, - PokemonIds.CHARMANDER: 4, - PokemonIds.CHARMELEON: 5, - PokemonIds.CHARIZARD: 6, - PokemonIds.SQUIRTLE: 7, - PokemonIds.WARTORTLE: 8, - PokemonIds.BLASTOISE: 9, - PokemonIds.CATERPIE: 10, - PokemonIds.METAPOD: 11, - PokemonIds.BUTTERFREE: 12, - PokemonIds.WEEDLE: 13, - PokemonIds.KAKUNA: 14, - PokemonIds.BEEDRILL: 15, - PokemonIds.PIDGEY: 16, - PokemonIds.PIDGEOTTO: 17, - PokemonIds.PIDGEOT: 18, - PokemonIds.RATTATA: 19, - PokemonIds.RATICATE: 20, - PokemonIds.SPEAROW: 21, - PokemonIds.FEAROW: 22, - PokemonIds.EKANS: 23, - PokemonIds.ARBOK: 24, - PokemonIds.PIKACHU: 25, - PokemonIds.RAICHU: 26, - PokemonIds.SANDSHREW: 27, - PokemonIds.SANDSLASH: 28, - PokemonIds.NIDORAN_F: 29, - PokemonIds.NIDORINA: 30, - PokemonIds.NIDOQUEEN: 31, - PokemonIds.NIDORAN_M: 32, - PokemonIds.NIDORINO: 33, - PokemonIds.NIDOKING: 34, - PokemonIds.CLEFAIRY: 35, - PokemonIds.CLEFABLE: 36, - PokemonIds.VULPIX: 37, - PokemonIds.NINETALES: 38, - PokemonIds.JIGGLYPUFF: 39, - PokemonIds.WIGGLYTUFF: 40, - PokemonIds.ZUBAT: 41, - PokemonIds.GOLBAT: 42, - PokemonIds.ODDISH: 43, - PokemonIds.GLOOM: 44, - PokemonIds.VILEPLUME: 45, - PokemonIds.PARAS: 46, - PokemonIds.PARASECT: 47, - PokemonIds.VENONAT: 48, - PokemonIds.VENOMOTH: 49, - PokemonIds.DIGLETT: 50, - PokemonIds.DUGTRIO: 51, - PokemonIds.MEOWTH: 52, - PokemonIds.PERSIAN: 53, - PokemonIds.PSYDUCK: 54, - PokemonIds.GOLDUCK: 55, - PokemonIds.MANKEY: 56, - PokemonIds.PRIMEAPE: 57, - PokemonIds.GROWLITHE: 58, - PokemonIds.ARCANINE: 59, - PokemonIds.POLIWAG: 60, - PokemonIds.POLIWHIRL: 61, - PokemonIds.POLIWRATH: 62, - PokemonIds.ABRA: 63, - PokemonIds.KADABRA: 64, - PokemonIds.ALAKAZAM: 65, - PokemonIds.MACHOP: 66, - PokemonIds.MACHOKE: 67, - PokemonIds.MACHAMP: 68, - PokemonIds.BELLSPROUT: 69, - PokemonIds.WEEPINBELL: 70, - PokemonIds.VICTREEBEL: 71, - PokemonIds.TENTACOOL: 72, - PokemonIds.TENTACRUEL: 73, - PokemonIds.GEODUDE: 74, - PokemonIds.GRAVELER: 75, - PokemonIds.GOLEM: 76, - PokemonIds.PONYTA: 77, - PokemonIds.RAPIDASH: 78, - PokemonIds.SLOWPOKE: 79, - PokemonIds.SLOWBRO: 80, - PokemonIds.MAGNEMITE: 81, - PokemonIds.MAGNETON: 82, - PokemonIds.FARFETCHD: 83, - PokemonIds.DODUO: 84, - PokemonIds.DODRIO: 85, - PokemonIds.SEEL: 86, - PokemonIds.DEWGONG: 87, - PokemonIds.GRIMER: 88, - PokemonIds.MUK: 89, - PokemonIds.SHELLDER: 90, - PokemonIds.CLOYSTER: 91, - PokemonIds.GASTLY: 92, - PokemonIds.HAUNTER: 93, - PokemonIds.GENGAR: 94, - PokemonIds.ONIX: 95, - PokemonIds.DROWZEE: 96, - PokemonIds.HYPNO: 97, - PokemonIds.KRABBY: 98, - PokemonIds.KINGLER: 99, - PokemonIds.VOLTORB: 100, - PokemonIds.ELECTRODE: 101, - PokemonIds.EXEGGCUTE: 102, - PokemonIds.EXEGGUTOR: 103, - PokemonIds.CUBONE: 104, - PokemonIds.MAROWAK: 105, - PokemonIds.HITMONLEE: 106, - PokemonIds.HITMONCHAN: 107, - PokemonIds.LICKITUNG: 108, - PokemonIds.KOFFING: 109, - PokemonIds.WEEZING: 110, - PokemonIds.RHYHORN: 111, - PokemonIds.RHYDON: 112, - PokemonIds.CHANSEY: 113, - PokemonIds.TANGELA: 114, - PokemonIds.KANGASKHAN: 115, - PokemonIds.HORSEA: 116, - PokemonIds.SEADRA: 117, - PokemonIds.GOLDEEN: 118, - PokemonIds.SEAKING: 119, - PokemonIds.STARYU: 120, - PokemonIds.STARMIE: 121, - PokemonIds.MR_MIME: 122, - PokemonIds.SCYTHER: 123, - PokemonIds.JYNX: 124, - PokemonIds.ELECTABUZZ: 125, - PokemonIds.MAGMAR: 126, - PokemonIds.PINSIR: 127, - PokemonIds.TAUROS: 128, - PokemonIds.MAGIKARP: 129, - PokemonIds.GYARADOS: 130, - PokemonIds.LAPRAS: 131, - PokemonIds.DITTO: 132, - PokemonIds.EEVEE: 133, - PokemonIds.VAPOREON: 134, - PokemonIds.JOLTEON: 135, - PokemonIds.FLAREON: 136, - PokemonIds.PORYGON: 137, - PokemonIds.OMANYTE: 138, - PokemonIds.OMASTAR: 139, - PokemonIds.KABUTO: 140, - PokemonIds.KABUTOPS: 141, - PokemonIds.AERODACTYL: 142, - PokemonIds.SNORLAX: 143, - PokemonIds.ARTICUNO: 144, - PokemonIds.ZAPDOS: 145, - PokemonIds.MOLTRES: 146, - PokemonIds.DRATINI: 147, - PokemonIds.DRAGONAIR: 148, - PokemonIds.DRAGONITE: 149, - PokemonIds.MEWTWO: 150, - PokemonIds.MEW: 151 + PokemonId.BULBASAUR: 1, + PokemonId.IVYSAUR: 2, + PokemonId.VENUSAUR: 3, + PokemonId.CHARMANDER: 4, + PokemonId.CHARMELEON: 5, + PokemonId.CHARIZARD: 6, + PokemonId.SQUIRTLE: 7, + PokemonId.WARTORTLE: 8, + PokemonId.BLASTOISE: 9, + PokemonId.CATERPIE: 10, + PokemonId.METAPOD: 11, + PokemonId.BUTTERFREE: 12, + PokemonId.WEEDLE: 13, + PokemonId.KAKUNA: 14, + PokemonId.BEEDRILL: 15, + PokemonId.PIDGEY: 16, + PokemonId.PIDGEOTTO: 17, + PokemonId.PIDGEOT: 18, + PokemonId.RATTATA: 19, + PokemonId.RATICATE: 20, + PokemonId.SPEAROW: 21, + PokemonId.FEAROW: 22, + PokemonId.EKANS: 23, + PokemonId.ARBOK: 24, + PokemonId.PIKACHU: 25, + PokemonId.RAICHU: 26, + PokemonId.SANDSHREW: 27, + PokemonId.SANDSLASH: 28, + PokemonId.NIDORAN_F: 29, + PokemonId.NIDORINA: 30, + PokemonId.NIDOQUEEN: 31, + PokemonId.NIDORAN_M: 32, + PokemonId.NIDORINO: 33, + PokemonId.NIDOKING: 34, + PokemonId.CLEFAIRY: 35, + PokemonId.CLEFABLE: 36, + PokemonId.VULPIX: 37, + PokemonId.NINETALES: 38, + PokemonId.JIGGLYPUFF: 39, + PokemonId.WIGGLYTUFF: 40, + PokemonId.ZUBAT: 41, + PokemonId.GOLBAT: 42, + PokemonId.ODDISH: 43, + PokemonId.GLOOM: 44, + PokemonId.VILEPLUME: 45, + PokemonId.PARAS: 46, + PokemonId.PARASECT: 47, + PokemonId.VENONAT: 48, + PokemonId.VENOMOTH: 49, + PokemonId.DIGLETT: 50, + PokemonId.DUGTRIO: 51, + PokemonId.MEOWTH: 52, + PokemonId.PERSIAN: 53, + PokemonId.PSYDUCK: 54, + PokemonId.GOLDUCK: 55, + PokemonId.MANKEY: 56, + PokemonId.PRIMEAPE: 57, + PokemonId.GROWLITHE: 58, + PokemonId.ARCANINE: 59, + PokemonId.POLIWAG: 60, + PokemonId.POLIWHIRL: 61, + PokemonId.POLIWRATH: 62, + PokemonId.ABRA: 63, + PokemonId.KADABRA: 64, + PokemonId.ALAKAZAM: 65, + PokemonId.MACHOP: 66, + PokemonId.MACHOKE: 67, + PokemonId.MACHAMP: 68, + PokemonId.BELLSPROUT: 69, + PokemonId.WEEPINBELL: 70, + PokemonId.VICTREEBEL: 71, + PokemonId.TENTACOOL: 72, + PokemonId.TENTACRUEL: 73, + PokemonId.GEODUDE: 74, + PokemonId.GRAVELER: 75, + PokemonId.GOLEM: 76, + PokemonId.PONYTA: 77, + PokemonId.RAPIDASH: 78, + PokemonId.SLOWPOKE: 79, + PokemonId.SLOWBRO: 80, + PokemonId.MAGNEMITE: 81, + PokemonId.MAGNETON: 82, + PokemonId.FARFETCHD: 83, + PokemonId.DODUO: 84, + PokemonId.DODRIO: 85, + PokemonId.SEEL: 86, + PokemonId.DEWGONG: 87, + PokemonId.GRIMER: 88, + PokemonId.MUK: 89, + PokemonId.SHELLDER: 90, + PokemonId.CLOYSTER: 91, + PokemonId.GASTLY: 92, + PokemonId.HAUNTER: 93, + PokemonId.GENGAR: 94, + PokemonId.ONIX: 95, + PokemonId.DROWZEE: 96, + PokemonId.HYPNO: 97, + PokemonId.KRABBY: 98, + PokemonId.KINGLER: 99, + PokemonId.VOLTORB: 100, + PokemonId.ELECTRODE: 101, + PokemonId.EXEGGCUTE: 102, + PokemonId.EXEGGUTOR: 103, + PokemonId.CUBONE: 104, + PokemonId.MAROWAK: 105, + PokemonId.HITMONLEE: 106, + PokemonId.HITMONCHAN: 107, + PokemonId.LICKITUNG: 108, + PokemonId.KOFFING: 109, + PokemonId.WEEZING: 110, + PokemonId.RHYHORN: 111, + PokemonId.RHYDON: 112, + PokemonId.CHANSEY: 113, + PokemonId.TANGELA: 114, + PokemonId.KANGASKHAN: 115, + PokemonId.HORSEA: 116, + PokemonId.SEADRA: 117, + PokemonId.GOLDEEN: 118, + PokemonId.SEAKING: 119, + PokemonId.STARYU: 120, + PokemonId.STARMIE: 121, + PokemonId.MR_MIME: 122, + PokemonId.SCYTHER: 123, + PokemonId.JYNX: 124, + PokemonId.ELECTABUZZ: 125, + PokemonId.MAGMAR: 126, + PokemonId.PINSIR: 127, + PokemonId.TAUROS: 128, + PokemonId.MAGIKARP: 129, + PokemonId.GYARADOS: 130, + PokemonId.LAPRAS: 131, + PokemonId.DITTO: 132, + PokemonId.EEVEE: 133, + PokemonId.VAPOREON: 134, + PokemonId.JOLTEON: 135, + PokemonId.FLAREON: 136, + PokemonId.PORYGON: 137, + PokemonId.OMANYTE: 138, + PokemonId.OMASTAR: 139, + PokemonId.KABUTO: 140, + PokemonId.KABUTOPS: 141, + PokemonId.AERODACTYL: 142, + PokemonId.SNORLAX: 143, + PokemonId.ARTICUNO: 144, + PokemonId.ZAPDOS: 145, + PokemonId.MOLTRES: 146, + PokemonId.DRATINI: 147, + PokemonId.DRAGONAIR: 148, + PokemonId.DRAGONITE: 149, + PokemonId.MEWTWO: 150, + PokemonId.MEW: 151 } _POKEMON_NAMES = { - PokemonIds.BULBASAUR: "Bulbasaur", - PokemonIds.IVYSAUR: "Ivysaur", - PokemonIds.VENUSAUR: "Venusaur", - PokemonIds.CHARMANDER: "Charmander", - PokemonIds.CHARMELEON: "Charmeleon", - PokemonIds.CHARIZARD: "Charizard", - PokemonIds.SQUIRTLE: "Squirtle", - PokemonIds.WARTORTLE: "Wartortle", - PokemonIds.BLASTOISE: "Blastoise", - PokemonIds.CATERPIE: "Caterpie", - PokemonIds.METAPOD: "Metapod", - PokemonIds.BUTTERFREE: "Butterfree", - PokemonIds.CATERPIE: "Weedle", - PokemonIds.KAKUNA: "Kakuna", - PokemonIds.BEEDRILL: "Beedrill", - PokemonIds.PIDGEY: "Pidgey", - PokemonIds.PIDGEOTTO: "Pidgeotto", - PokemonIds.PIDGEOT: "Pidgeot", - PokemonIds.RATTATA: "Rattata", - PokemonIds.RATICATE: "Raticate", - PokemonIds.SPEAROW: "Spearow", - PokemonIds.FEAROW: "Fearow", - PokemonIds.EKANS: "Ekans", - PokemonIds.ARBOK: "Arbok", - PokemonIds.PIKACHU: "Pikachu", - PokemonIds.RAICHU: "Raichu", - PokemonIds.SANDSHREW: "Sandshrew", - PokemonIds.SANDSLASH: "Sandslash", - PokemonIds.NIDORAN_F: "Nidoran♀", - PokemonIds.NIDORINA: "Nidorina", - PokemonIds.NIDOQUEEN: "Nidoqueen", - PokemonIds.NIDORAN_M: "Nidoran♂", - PokemonIds.NIDORINO: "Nidorino", - PokemonIds.NIDOKING: "Nidoking", - PokemonIds.CLEFAIRY: "Clefairy", - PokemonIds.CLEFABLE: "Clefable", - PokemonIds.VULPIX: "Vulpix", - PokemonIds.NINETALES: "Ninetales", - PokemonIds.JIGGLYPUFF: "Jigglypuff", - PokemonIds.WIGGLYTUFF: "Wigglytuff", - PokemonIds.ZUBAT: "Zubat", - PokemonIds.GOLBAT: "Golbat", - PokemonIds.ODDISH: "Oddish", - PokemonIds.GLOOM: "Gloom", - PokemonIds.VILEPLUME: "Vileplume", - PokemonIds.PARAS: "Paras", - PokemonIds.PARASECT: "Parasect", - PokemonIds.VENONAT: "Venonat", - PokemonIds.VENOMOTH: "Venomoth", - PokemonIds.DIGLETT: "Diglett", - PokemonIds.DUGTRIO: "Dugtrio", - PokemonIds.MEOWTH: "Meowth", - PokemonIds.PERSIAN: "Persian", - PokemonIds.PSYDUCK: "Psyduck", - PokemonIds.GOLDUCK: "Golduck", - PokemonIds.MANKEY: "Mankey", - PokemonIds.PRIMEAPE: "Primeape", - PokemonIds.GROWLITHE: "Growlithe", - PokemonIds.ARCANINE: "Arcanine", - PokemonIds.POLIWAG: "Poliwag", - PokemonIds.POLIWHIRL: "Poliwhirl", - PokemonIds.POLIWRATH: "Poliwrath", - PokemonIds.ABRA: "Abra", - PokemonIds.KADABRA: "Kadabra", - PokemonIds.ALAKAZAM: "Alakazam", - PokemonIds.MACHOP: "Machop", - PokemonIds.MACHOKE: "Machoke", - PokemonIds.MACHAMP: "Machamp", - PokemonIds.BELLSPROUT: "Bellsprout", - PokemonIds.WEEPINBELL: "Weepinbell", - PokemonIds.VICTREEBEL: "Victreebel", - PokemonIds.TENTACOOL: "Tentacool", - PokemonIds.TENTACRUEL: "Tentacruel", - PokemonIds.GEODUDE: "Geodude", - PokemonIds.GRAVELER: "Graveler", - PokemonIds.GOLEM: "Golem", - PokemonIds.PONYTA: "Ponyta", - PokemonIds.RAPIDASH: "Rapidash", - PokemonIds.SLOWPOKE: "Slowpoke", - PokemonIds.SLOWBRO: "Slowbro", - PokemonIds.MAGNEMITE: "Magnemite", - PokemonIds.MAGNETON: "Magneton", - PokemonIds.FARFETCHD: "Farfetch’d", - PokemonIds.DODUO: "Doduo", - PokemonIds.DODRIO: "Dodrio", - PokemonIds.SEEL: "Seel", - PokemonIds.DEWGONG: "Dewgong", - PokemonIds.GRIMER: "Grimer", - PokemonIds.MUK: "Muk", - PokemonIds.SHELLDER: "Shellder", - PokemonIds.CLOYSTER: "Cloyster", - PokemonIds.GASTLY: "Gastly", - PokemonIds.HAUNTER: "Haunter", - PokemonIds.GENGAR: "Gengar", - PokemonIds.ONIX: "Onix", - PokemonIds.DROWZEE: "Drowzee", - PokemonIds.HYPNO: "Hypno", - PokemonIds.KRABBY: "Krabby", - PokemonIds.KINGLER: "Kingler", - PokemonIds.VOLTORB: "Voltorb", - PokemonIds.ELECTRODE: "Electrode", - PokemonIds.EXEGGCUTE: "Exeggcute", - PokemonIds.EXEGGUTOR: "Exeggutor", - PokemonIds.CUBONE: "Cubone", - PokemonIds.MAROWAK: "Marowak", - PokemonIds.HITMONLEE: "Hitmonlee", - PokemonIds.HITMONCHAN: "Hitmonchan", - PokemonIds.LICKITUNG: "Lickitung", - PokemonIds.KOFFING: "Koffing", - PokemonIds.WEEZING: "Weezing", - PokemonIds.RHYHORN: "Rhyhorn", - PokemonIds.RHYDON: "Rhydon", - PokemonIds.CHANSEY: "Chansey", - PokemonIds.TANGELA: "Tangela", - PokemonIds.KANGASKHAN: "Kangaskhan", - PokemonIds.HORSEA: "Horsea", - PokemonIds.SEADRA: "Seadra", - PokemonIds.GOLDEEN: "Goldeen", - PokemonIds.SEAKING: "Seaking", - PokemonIds.STARYU: "Staryu", - PokemonIds.STARMIE: "Starmie", - PokemonIds.MR_MIME: "Mr. Mime", - PokemonIds.SCYTHER: "Scyther", - PokemonIds.JYNX: "Jynx", - PokemonIds.ELECTABUZZ: "Electabuzz", - PokemonIds.MAGMAR: "Magmar", - PokemonIds.PINSIR: "Pinsir", - PokemonIds.TAUROS: "Tauros", - PokemonIds.MAGIKARP: "Magikarp", - PokemonIds.GYARADOS: "Gyarados", - PokemonIds.LAPRAS: "Lapras", - PokemonIds.DITTO: "Ditto", - PokemonIds.EEVEE: "Eevee", - PokemonIds.VAPOREON: "Vaporeon", - PokemonIds.JOLTEON: "Jolteon", - PokemonIds.FLAREON: "Flareon", - PokemonIds.PORYGON: "Porygon", - PokemonIds.OMANYTE: "Omanyte", - PokemonIds.OMASTAR: "Omastar", - PokemonIds.KABUTO: "Kabuto", - PokemonIds.KABUTOPS: "Kabutops", - PokemonIds.AERODACTYL: "Aerodactyl", - PokemonIds.SNORLAX: "Snorlax", - PokemonIds.ARTICUNO: "Articuno", - PokemonIds.ZAPDOS: "Zapdos", - PokemonIds.MOLTRES: "Moltres", - PokemonIds.DRATINI: "Dratini", - PokemonIds.DRAGONAIR: "Dragonair", - PokemonIds.DRAGONITE: "Dragonite", - PokemonIds.MEWTWO: "Mewtwo", - PokemonIds.MEW: "Mew", + PokemonId.BULBASAUR: "Bulbasaur", + PokemonId.IVYSAUR: "Ivysaur", + PokemonId.VENUSAUR: "Venusaur", + PokemonId.CHARMANDER: "Charmander", + PokemonId.CHARMELEON: "Charmeleon", + PokemonId.CHARIZARD: "Charizard", + PokemonId.SQUIRTLE: "Squirtle", + PokemonId.WARTORTLE: "Wartortle", + PokemonId.BLASTOISE: "Blastoise", + PokemonId.CATERPIE: "Caterpie", + PokemonId.METAPOD: "Metapod", + PokemonId.BUTTERFREE: "Butterfree", + PokemonId.CATERPIE: "Weedle", + PokemonId.KAKUNA: "Kakuna", + PokemonId.BEEDRILL: "Beedrill", + PokemonId.PIDGEY: "Pidgey", + PokemonId.PIDGEOTTO: "Pidgeotto", + PokemonId.PIDGEOT: "Pidgeot", + PokemonId.RATTATA: "Rattata", + PokemonId.RATICATE: "Raticate", + PokemonId.SPEAROW: "Spearow", + PokemonId.FEAROW: "Fearow", + PokemonId.EKANS: "Ekans", + PokemonId.ARBOK: "Arbok", + PokemonId.PIKACHU: "Pikachu", + PokemonId.RAICHU: "Raichu", + PokemonId.SANDSHREW: "Sandshrew", + PokemonId.SANDSLASH: "Sandslash", + PokemonId.NIDORAN_F: "Nidoran♀", + PokemonId.NIDORINA: "Nidorina", + PokemonId.NIDOQUEEN: "Nidoqueen", + PokemonId.NIDORAN_M: "Nidoran♂", + PokemonId.NIDORINO: "Nidorino", + PokemonId.NIDOKING: "Nidoking", + PokemonId.CLEFAIRY: "Clefairy", + PokemonId.CLEFABLE: "Clefable", + PokemonId.VULPIX: "Vulpix", + PokemonId.NINETALES: "Ninetales", + PokemonId.JIGGLYPUFF: "Jigglypuff", + PokemonId.WIGGLYTUFF: "Wigglytuff", + PokemonId.ZUBAT: "Zubat", + PokemonId.GOLBAT: "Golbat", + PokemonId.ODDISH: "Oddish", + PokemonId.GLOOM: "Gloom", + PokemonId.VILEPLUME: "Vileplume", + PokemonId.PARAS: "Paras", + PokemonId.PARASECT: "Parasect", + PokemonId.VENONAT: "Venonat", + PokemonId.VENOMOTH: "Venomoth", + PokemonId.DIGLETT: "Diglett", + PokemonId.DUGTRIO: "Dugtrio", + PokemonId.MEOWTH: "Meowth", + PokemonId.PERSIAN: "Persian", + PokemonId.PSYDUCK: "Psyduck", + PokemonId.GOLDUCK: "Golduck", + PokemonId.MANKEY: "Mankey", + PokemonId.PRIMEAPE: "Primeape", + PokemonId.GROWLITHE: "Growlithe", + PokemonId.ARCANINE: "Arcanine", + PokemonId.POLIWAG: "Poliwag", + PokemonId.POLIWHIRL: "Poliwhirl", + PokemonId.POLIWRATH: "Poliwrath", + PokemonId.ABRA: "Abra", + PokemonId.KADABRA: "Kadabra", + PokemonId.ALAKAZAM: "Alakazam", + PokemonId.MACHOP: "Machop", + PokemonId.MACHOKE: "Machoke", + PokemonId.MACHAMP: "Machamp", + PokemonId.BELLSPROUT: "Bellsprout", + PokemonId.WEEPINBELL: "Weepinbell", + PokemonId.VICTREEBEL: "Victreebel", + PokemonId.TENTACOOL: "Tentacool", + PokemonId.TENTACRUEL: "Tentacruel", + PokemonId.GEODUDE: "Geodude", + PokemonId.GRAVELER: "Graveler", + PokemonId.GOLEM: "Golem", + PokemonId.PONYTA: "Ponyta", + PokemonId.RAPIDASH: "Rapidash", + PokemonId.SLOWPOKE: "Slowpoke", + PokemonId.SLOWBRO: "Slowbro", + PokemonId.MAGNEMITE: "Magnemite", + PokemonId.MAGNETON: "Magneton", + PokemonId.FARFETCHD: "Farfetch’d", + PokemonId.DODUO: "Doduo", + PokemonId.DODRIO: "Dodrio", + PokemonId.SEEL: "Seel", + PokemonId.DEWGONG: "Dewgong", + PokemonId.GRIMER: "Grimer", + PokemonId.MUK: "Muk", + PokemonId.SHELLDER: "Shellder", + PokemonId.CLOYSTER: "Cloyster", + PokemonId.GASTLY: "Gastly", + PokemonId.HAUNTER: "Haunter", + PokemonId.GENGAR: "Gengar", + PokemonId.ONIX: "Onix", + PokemonId.DROWZEE: "Drowzee", + PokemonId.HYPNO: "Hypno", + PokemonId.KRABBY: "Krabby", + PokemonId.KINGLER: "Kingler", + PokemonId.VOLTORB: "Voltorb", + PokemonId.ELECTRODE: "Electrode", + PokemonId.EXEGGCUTE: "Exeggcute", + PokemonId.EXEGGUTOR: "Exeggutor", + PokemonId.CUBONE: "Cubone", + PokemonId.MAROWAK: "Marowak", + PokemonId.HITMONLEE: "Hitmonlee", + PokemonId.HITMONCHAN: "Hitmonchan", + PokemonId.LICKITUNG: "Lickitung", + PokemonId.KOFFING: "Koffing", + PokemonId.WEEZING: "Weezing", + PokemonId.RHYHORN: "Rhyhorn", + PokemonId.RHYDON: "Rhydon", + PokemonId.CHANSEY: "Chansey", + PokemonId.TANGELA: "Tangela", + PokemonId.KANGASKHAN: "Kangaskhan", + PokemonId.HORSEA: "Horsea", + PokemonId.SEADRA: "Seadra", + PokemonId.GOLDEEN: "Goldeen", + PokemonId.SEAKING: "Seaking", + PokemonId.STARYU: "Staryu", + PokemonId.STARMIE: "Starmie", + PokemonId.MR_MIME: "Mr. Mime", + PokemonId.SCYTHER: "Scyther", + PokemonId.JYNX: "Jynx", + PokemonId.ELECTABUZZ: "Electabuzz", + PokemonId.MAGMAR: "Magmar", + PokemonId.PINSIR: "Pinsir", + PokemonId.TAUROS: "Tauros", + PokemonId.MAGIKARP: "Magikarp", + PokemonId.GYARADOS: "Gyarados", + PokemonId.LAPRAS: "Lapras", + PokemonId.DITTO: "Ditto", + PokemonId.EEVEE: "Eevee", + PokemonId.VAPOREON: "Vaporeon", + PokemonId.JOLTEON: "Jolteon", + PokemonId.FLAREON: "Flareon", + PokemonId.PORYGON: "Porygon", + PokemonId.OMANYTE: "Omanyte", + PokemonId.OMASTAR: "Omastar", + PokemonId.KABUTO: "Kabuto", + PokemonId.KABUTOPS: "Kabutops", + PokemonId.AERODACTYL: "Aerodactyl", + PokemonId.SNORLAX: "Snorlax", + PokemonId.ARTICUNO: "Articuno", + PokemonId.ZAPDOS: "Zapdos", + PokemonId.MOLTRES: "Moltres", + PokemonId.DRATINI: "Dratini", + PokemonId.DRAGONAIR: "Dragonair", + PokemonId.DRAGONITE: "Dragonite", + PokemonId.MEWTWO: "Mewtwo", + PokemonId.MEW: "Mew", } \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/sprites.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/sprites.py index 7fa3c1bf7..590648de3 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/sprites.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/sprites.py @@ -1,6 +1,6 @@ from enum import Enum -class Sprites(Enum): +class Sprite(Enum): RED = 0x01 BLUE = 0x02 OAK = 0x03 diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/status.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/status.py index 3d5e005d8..7055afe90 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/status.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/constants/status.py @@ -1,6 +1,6 @@ from enum import Enum -class Statuses(Enum): +class Status(Enum): ASLEEP = 4 POISONED = 8 BURNED = 16 diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py index e32950f55..f7ea8a8e7 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py @@ -12,7 +12,6 @@ from pyboy.utils import WindowEvent from pyboy.logger import logger from ..base_plugin import PyBoyGameWrapper -from .data.constants.status import Statuses from .data.memory_addrs.misc import MONEY_ADDR from .core.pokedex import Pokedex from .core.pokemon import Pokemon From 488f56c55ab8b427b361b53fee51959944f23f17 Mon Sep 17 00:00:00 2001 From: SnarkAttack Date: Wed, 8 Nov 2023 14:59:15 -0500 Subject: [PATCH 52/74] Fix issue where we needed enum value not enum to get correct list slice --- pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py index 3c357f450..513c25304 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py @@ -58,4 +58,4 @@ def num_badges(self): return sum(self._badges) def has_badge(self, badge : Badge): - return self._badges[badge] == 1 \ No newline at end of file + return self._badges[badge.value] == 1 \ No newline at end of file From 754ac34b4174d861a68d068227f6211e50642b37 Mon Sep 17 00:00:00 2001 From: SnarkAttack Date: Wed, 8 Nov 2023 15:10:48 -0500 Subject: [PATCH 53/74] Convert all memory address enums to singular as well --- .../core/mem_manager.py | 31 ++++------- .../game_wrapper_pokemon_gen1/core/player.py | 54 ++++++++++++------- .../game_wrapper_pokemon_gen1/core/pokemon.py | 10 ++-- .../data/memory_addrs/player.py | 2 +- .../data/memory_addrs/pokemon.py | 4 +- .../data/memory_addrs/sprites.py | 4 +- 6 files changed, 57 insertions(+), 48 deletions(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py index 26f78141d..84a81d542 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py @@ -82,25 +82,16 @@ def read_text_from_memory(self, address, num_bytes): text += chr(value - ASCII_DELTA) return text - # def set_text(self, text, address): - # """Sets text at address. + def write_text_to_memory_text(self, text, address, num_bytes=1): + """Sets text at address. - # Will always add a string terminator (80) at the end. - # """ - # i = 0 - # for character in text: - # try: - # self.pyboy.set_memory_value(address + i, MemoryManager.get_character_index(character)) - # i += 1 - # except: - # pass - # self.pyboy.set_memory_value(address + i, STRING_TERMINATOR) + Will always add a string terminator (80) at the end. + """ + + terminated_text = text + STRING_TERMINATOR + # TODO: Check that this isn't an odd-by-one issue + assert terminated_text <= num_bytes - # def set_rom_text(self, text, bank, address): - # i = 0 - # for character in text: - # try: - # self.pyboy.override_memory_value(bank, address + i, get_character_index(character)) - # i += 1 - # except: - # pass \ No newline at end of file + i = 0 + for i, chr in enumerate(text): + self.pyboy.set_memory_value(address + i, MemoryManager.get_character_index(chr)) \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py index 513c25304..ddac3159a 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py @@ -1,4 +1,4 @@ -from ..data.memory_addrs.player import PlayerAddresses +from ..data.memory_addrs.player import PlayerAddress from ..data.constants.pokemon import PokemonId from ..data.constants.misc import Badge @@ -14,23 +14,10 @@ def __init__(self, self._pokemon_in_party = pokemon_in_party self._badges = badges self._money = money - - @staticmethod - def load_player(mem_manager): - - name = mem_manager.read_text_from_memory(PlayerAddresses.NAME[0], PlayerAddresses.NAME[1]) - - num_pokemon_in_party = mem_manager.read_hex_from_memory(PlayerAddresses.NUM_POKEMON_IN_PARTY[0]) - - pokemon_in_party = [PokemonId(mem_manager.read_hex_from_memory(PlayerAddresses.NUM_POKEMON_IN_PARTY[0]+i+1)) - for i in range(num_pokemon_in_party)] - - badges = mem_manager.read_bitfield_from_memory(PlayerAddresses.BADGES[0], reverse=True) - - money = mem_manager.read_bcd_from_memory(PlayerAddresses.MONEY[0], PlayerAddresses.MONEY[1]) - - return Player(name, pokemon_in_party, badges, money) + ''' + Getters and setters + ''' @property def name(self): return self._name @@ -57,5 +44,36 @@ def num_pokemon_in_party(self): def num_badges(self): return sum(self._badges) + ''' + Badge functionality + ''' def has_badge(self, badge : Badge): - return self._badges[badge.value] == 1 \ No newline at end of file + return self._badges[badge.value] == 1 + + def give_badge(self, badge : Badge): + self._badges[badge.value] == 1 + + def remove_badge(self, badge : Badge): + self._badges[badge.value] == 0 + + @staticmethod + def load_player(mem_manager): + + name = mem_manager.read_text_from_memory(PlayerAddress.NAME[0], PlayerAddress.NAME[1]) + + num_pokemon_in_party = mem_manager.read_hex_from_memory(PlayerAddress.NUM_POKEMON_IN_PARTY[0]) + + pokemon_in_party = [PokemonId(mem_manager.read_hex_from_memory(PlayerAddress.NUM_POKEMON_IN_PARTY[0]+i+1)) + for i in range(num_pokemon_in_party)] + + badges = mem_manager.read_bitfield_from_memory(PlayerAddress.BADGES[0]) + + money = mem_manager.read_bcd_from_memory(PlayerAddress.MONEY[0], PlayerAddress.MONEY[1]) + + return Player(name, pokemon_in_party, badges, money) + + def save_player(self, mem_manager): + + mem_manager.write_text_to_memory(self._name, PlayerAddress.NAME[0]) + + \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py index a3a42bc9b..ac21bf4e6 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py @@ -1,4 +1,4 @@ -from ..data.memory_addrs.pokemon import PokemonBaseAddrs, PokemonMemoryOffsets +from ..data.memory_addrs.pokemon import PokemonBaseAddress, PokemonMemoryOffset from ..data.constants.pokemon import PokemonId, _POKEMON_NAMES, _POKEMON_POKEDEX_INDEX from .move import Move @@ -150,13 +150,13 @@ def _load_pokemon_from_address(mem_manager, pokemon_base_address, in_party): pokemon_values = [] if in_party: - it = list(PokemonMemoryOffsets) + it = list(PokemonMemoryOffset) else: # When checking a Pokemon in the box, it does not have the second # level field or any of its stats saved in memory - it = list(PokemonMemoryOffsets)[:-6] + it = list(PokemonMemoryOffset)[:-6] - for offset_enum in PokemonMemoryOffsets: + for offset_enum in PokemonMemoryOffset: offset, num_bytes = offset_enum.value[0], offset_enum.value[1] memory_value = mem_manager.read_hex_from_memory(pokemon_base_address+offset, num_bytes) pokemon_values.append(memory_value) @@ -166,7 +166,7 @@ def _load_pokemon_from_address(mem_manager, pokemon_base_address, in_party): @classmethod def load_pokemon_from_party(cls, mem_manager, party_location): # party_location goes from 1-6 - pokemon_base_address = list(PokemonBaseAddrs)[party_location-1].value + pokemon_base_address = list(PokemonBaseAddress)[party_location-1].value return cls._load_pokemon_from_address(mem_manager, pokemon_base_address, in_party=True) def _generate_move_str(self): diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/player.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/player.py index 3c32bc87e..942809b6c 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/player.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/player.py @@ -1,6 +1,6 @@ from enum import Enum -class PlayerAddresses: +class PlayerAddress(Enum): NAME = (0xD158, 10) NUM_POKEMON_IN_PARTY = (0xD163, 1) BADGES = (0xD356, 1) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/pokemon.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/pokemon.py index d15272465..53430e71f 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/pokemon.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/pokemon.py @@ -1,7 +1,7 @@ # Pokemon locations in memory from enum import Enum -class PokemonBaseAddrs(Enum): +class PokemonBaseAddress(Enum): POKEMON_1 = 0xD16B POKEMON_2 = 0xD197 POKEMON_3 = 0xD1C3 @@ -11,7 +11,7 @@ class PokemonBaseAddrs(Enum): # Offsets for Pokemon data access # Structure is (offset, num bytes) -class PokemonMemoryOffsets(Enum): +class PokemonMemoryOffset(Enum): ID = (0x0, 1) CURRENT_HP = (0x1, 2) BOX_LEVEL = (0x3, 1) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/sprites.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/sprites.py index 17ddcf984..d9e9ab0f0 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/sprites.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/sprites.py @@ -5,7 +5,7 @@ from enum import Enum -class SpriteBaseAddrs(Enum): +class SpriteBaseAddress(Enum): PLAYER_SPRITE = 0xC100 # Player is ALWAYS sprite 0 SPRITE_1 = 0xC110 SPIRITE_2 = 0xC120 @@ -23,7 +23,7 @@ class SpriteBaseAddrs(Enum): SPRITE_14 = 0xC1E0 SPRITE_15 = 0xC1F0 -class SpriteMemoryOffsets(Enum): +class SpriteMemoryOffset(Enum): PICTURE_ID = 0x0 MOVEMENT_STATUS = 0x1 # (0: uninitialized, 1: ready, 2: delayed, 3: moving) # TODO: Figure out exactly what this data looks like From d196a60cb36ce7619c8ff0c82b432f17ec518a52 Mon Sep 17 00:00:00 2001 From: SnarkAttack Date: Wed, 8 Nov 2023 15:53:44 -0500 Subject: [PATCH 54/74] Add write functions to match corresponding reads in memory and implement first pass at Player class write to memory --- .../core/mem_manager.py | 47 +++++++++++++++++-- .../game_wrapper_pokemon_gen1/core/player.py | 6 +++ 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py index 84a81d542..b4f8770d3 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py @@ -18,6 +18,16 @@ def _byte_to_bitfield(n, reverse : bool): return bitlist + @staticmethod + def _bitfield_to_byte(bitlist, reverse : bool): + + if reverse: + bitlist.reverse() + + bit_str = ''.join(bitlist) + + return int(bit_str) + @staticmethod def get_character_index(character): if character == ' ': @@ -38,31 +48,62 @@ def get_character_index(character): def _read_byte(self, addr): return self.pyboy.get_memory_value(addr) + def _write_byte(self, value, addr): + return self.pyboy.set_memory_value(addr, value) + def read_address_from_memory(self, addr, num_bytes=1): p_addr = 0 for i in range(num_bytes): - p_addr += self.pyboy.get_memory_value(addr+i) << i*8 + p_addr += self._read_byte(addr+i) << i*8 return p_addr def read_hex_from_memory(self, addr, num_bytes=1): bytes = [] for i in range(num_bytes): - bytes.append(self.pyboy.get_memory_value(addr + i)) + bytes.append(self._read_byte(addr + i)) # Do not believe there is ever a case where we would # need to read this in little endian for Pokemon gen 1 return int.from_bytes(bytes, byteorder='big') + + def write_hex_to_memory(self, value, addr, num_bytes=1): + bytes = value.to_bytes(2, byteorder='big') + assert len(bytes) == num_bytes + for i, byte in enumerate(bytes): + self._write_byte(addr + i, byte) def read_bcd_from_memory(self, addr, num_bytes=1): byte_str = "" for i in range(num_bytes): - byte_str += "%x"%self.pyboy.get_memory_value(addr+i) + byte_str += "%x"%self._read_byte(addr+i) return int(byte_str) + def write_bcd_to_memory(self, value, addr, num_bytes=1): + val_str = str(value) + assert len(val_str) <= num_bytes*2 + + padded_val = val_str.zfill(num_bytes*2) + for i in range(num_bytes): + sub_val = int(padded_val[i*2:(i*2)+2], 16) + self._write_byte(sub_val, addr+i) + def read_bitfield_from_memory(self, addr, num_bytes=1, reverse=False): bits = [] for i in range(num_bytes): bits.extend(MemoryManager._byte_to_bitfield(self._read_byte(addr+i), reverse)) return bits + + def write_bitlist_to_memory(self, value, addr, num_bytes=1, reverse=False): + + # TODO: This check might be too restrictive + assert len(value) % 8 == 0 + # TODO: Maybe don't need this check if we trust users to make value fit + assert len(value)/8 == num_bytes + + for i in range(num_bytes): + bit_list_start = i*8 + sub_bit_list = value[bit_list_start:bit_list_start+8] + byte_val = MemoryManager._bitfield_to_byte(sub_bit_list, reverse) + self._write_byte(byte_val, addr+i) def read_text_from_memory(self, address, num_bytes): """ diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py index ddac3159a..d60ace8fe 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py @@ -75,5 +75,11 @@ def load_player(mem_manager): def save_player(self, mem_manager): mem_manager.write_text_to_memory(self._name, PlayerAddress.NAME[0]) + mem_manager.write_hex_to_memory(self.num_pokemon_in_party, PlayerAddress.NUM_POKEMON_IN_PARTY[0]) + # TODO: Figure out the loading and unloading of Pokemon in party, as that should be in tandem with + # Pokemon class so that data does not get out of sync + mem_manager.write_bitlist_to_memory(PlayerAddress.BADGES[0]) + mem_manager.write_bcd_to_memory(self._money, PlayerAddress.MONEY[0], PlayerAddress.MONEY[1]) + \ No newline at end of file From e2dacc354aaa7f0bcb9d3d9e03436f3dbdbca043 Mon Sep 17 00:00:00 2001 From: SnarkAttack Date: Wed, 8 Nov 2023 15:55:07 -0500 Subject: [PATCH 55/74] Add MemoryAdressEnum, which all memory address data will inherit from and will let us encapsulate memory data for read and write calls --- .../data/memory_addrs/base.py | 11 +++++++++++ .../data/memory_addrs/misc.py | 1 - .../data/memory_addrs/player.py | 4 ++-- .../data/memory_addrs/pokemon.py | 3 ++- 4 files changed, 15 insertions(+), 4 deletions(-) create mode 100644 pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/base.py diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/base.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/base.py new file mode 100644 index 000000000..b2f6588bf --- /dev/null +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/base.py @@ -0,0 +1,11 @@ +from enum import Enum + +class MemoryAddressEnum(Enum): + + def __str__(self): + return f"Memory address: {self.value[0]}: Length: {self.value[1]}" + + def add_addr(self, offset): + # Super hacky way to 'add' an offset to an enum, which just + # returns a new tuple with the right values + return (self.value[0]+offset, self.value[1]) \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/misc.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/misc.py index 3b57b1829..a71a58c7f 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/misc.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/misc.py @@ -1,2 +1 @@ - MONEY_ADDR = (0xD347, 3) \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/player.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/player.py index 942809b6c..5aad0ff11 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/player.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/player.py @@ -1,6 +1,6 @@ -from enum import Enum +from base import MemoryAddressEnum -class PlayerAddress(Enum): +class PlayerAddress(MemoryAddressEnum): NAME = (0xD158, 10) NUM_POKEMON_IN_PARTY = (0xD163, 1) BADGES = (0xD356, 1) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/pokemon.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/pokemon.py index 53430e71f..ec449205a 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/pokemon.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/pokemon.py @@ -1,5 +1,6 @@ # Pokemon locations in memory from enum import Enum +from base import MemoryAddressEnum class PokemonBaseAddress(Enum): POKEMON_1 = 0xD16B @@ -11,7 +12,7 @@ class PokemonBaseAddress(Enum): # Offsets for Pokemon data access # Structure is (offset, num bytes) -class PokemonMemoryOffset(Enum): +class PokemonMemoryOffset(MemoryAddressEnum): ID = (0x0, 1) CURRENT_HP = (0x1, 2) BOX_LEVEL = (0x3, 1) From 403f8c24678da46b8645ea02c9dfc9e53015488e Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Wed, 8 Nov 2023 16:19:40 -0500 Subject: [PATCH 56/74] Add wrapper functions to write MemoryAddressEnums without having to open them outside of MemoryManager --- .../core/mem_manager.py | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py index b4f8770d3..9c19f18ce 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py @@ -65,18 +65,27 @@ def read_hex_from_memory(self, addr, num_bytes=1): # need to read this in little endian for Pokemon gen 1 return int.from_bytes(bytes, byteorder='big') + def read_hex_from_mem_addr(self, mem_addr): + return self.read_hex_from_memory(self, mem_addr[0], mem_addr[1]) + def write_hex_to_memory(self, value, addr, num_bytes=1): bytes = value.to_bytes(2, byteorder='big') assert len(bytes) == num_bytes for i, byte in enumerate(bytes): self._write_byte(addr + i, byte) + def write_hex_to_mem_addr(self, value, mem_addr): + self.write_hex_to_memory(value, mem_addr[0], mem_addr[1]) + def read_bcd_from_memory(self, addr, num_bytes=1): byte_str = "" for i in range(num_bytes): byte_str += "%x"%self._read_byte(addr+i) return int(byte_str) + def read_bcd_from_mem_addr(self, mem_addr): + return self.read_bcd_from_memory(mem_addr[0], mem_addr[1]) + def write_bcd_to_memory(self, value, addr, num_bytes=1): val_str = str(value) assert len(val_str) <= num_bytes*2 @@ -85,6 +94,9 @@ def write_bcd_to_memory(self, value, addr, num_bytes=1): for i in range(num_bytes): sub_val = int(padded_val[i*2:(i*2)+2], 16) self._write_byte(sub_val, addr+i) + + def write_bcd_to_mem_addr(self, value, mem_addr): + self.write_bcd_to_memory(value, mem_addr[0], mem_addr[1]) def read_bitfield_from_memory(self, addr, num_bytes=1, reverse=False): bits = [] @@ -92,6 +104,9 @@ def read_bitfield_from_memory(self, addr, num_bytes=1, reverse=False): bits.extend(MemoryManager._byte_to_bitfield(self._read_byte(addr+i), reverse)) return bits + def read_bitfield_from_mem_addr(self, mem_addr): + return self.read_bitfield_from_memory(mem_addr[0], mem_addr[1]) + def write_bitlist_to_memory(self, value, addr, num_bytes=1, reverse=False): # TODO: This check might be too restrictive @@ -105,6 +120,9 @@ def write_bitlist_to_memory(self, value, addr, num_bytes=1, reverse=False): byte_val = MemoryManager._bitfield_to_byte(sub_bit_list, reverse) self._write_byte(byte_val, addr+i) + def write_bitlist_to_mem_addr(self, value, mem_addr): + self.write_bitlist_to_memory(value, mem_addr[0], mem_addr[1]) + def read_text_from_memory(self, address, num_bytes): """ Retrieves a string from a given address. @@ -123,6 +141,9 @@ def read_text_from_memory(self, address, num_bytes): text += chr(value - ASCII_DELTA) return text + def read_text_from_mem_addr(self, mem_addr): + return self.read_text_from_memory(mem_addr[0], mem_addr[1]) + def write_text_to_memory_text(self, text, address, num_bytes=1): """Sets text at address. @@ -135,4 +156,7 @@ def write_text_to_memory_text(self, text, address, num_bytes=1): i = 0 for i, chr in enumerate(text): - self.pyboy.set_memory_value(address + i, MemoryManager.get_character_index(chr)) \ No newline at end of file + self.pyboy.set_memory_value(address + i, MemoryManager.get_character_index(chr)) + + def write_text_to_mem_addr(self, text, mem_addr): + self.write_text_to_memory(text, mem_addr[0], mem_addr[1]) \ No newline at end of file From f30bdc36543fcf397fd6f2a11f2fb30ece992990 Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Wed, 8 Nov 2023 17:20:01 -0500 Subject: [PATCH 57/74] Fix issues with MemoryAddressEnum working in read/write calls --- .../core/mem_manager.py | 10 +++++----- .../game_wrapper_pokemon_gen1/core/player.py | 18 +++++++++--------- .../game_wrapper_pokemon_gen1/core/pokedex.py | 8 ++++---- .../game_wrapper_pokemon_gen1/core/pokemon.py | 4 ++-- .../data/memory_addrs/base.py | 1 + .../data/memory_addrs/player.py | 2 +- .../data/memory_addrs/pokemon.py | 2 +- 7 files changed, 23 insertions(+), 22 deletions(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py index 9c19f18ce..a3a4d3703 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py @@ -66,7 +66,7 @@ def read_hex_from_memory(self, addr, num_bytes=1): return int.from_bytes(bytes, byteorder='big') def read_hex_from_mem_addr(self, mem_addr): - return self.read_hex_from_memory(self, mem_addr[0], mem_addr[1]) + return self.read_hex_from_memory(mem_addr[0], mem_addr[1]) def write_hex_to_memory(self, value, addr, num_bytes=1): bytes = value.to_bytes(2, byteorder='big') @@ -104,8 +104,8 @@ def read_bitfield_from_memory(self, addr, num_bytes=1, reverse=False): bits.extend(MemoryManager._byte_to_bitfield(self._read_byte(addr+i), reverse)) return bits - def read_bitfield_from_mem_addr(self, mem_addr): - return self.read_bitfield_from_memory(mem_addr[0], mem_addr[1]) + def read_bitfield_from_mem_addr(self, mem_addr, reverse=False): + return self.read_bitfield_from_memory(mem_addr[0], mem_addr[1], reverse) def write_bitlist_to_memory(self, value, addr, num_bytes=1, reverse=False): @@ -120,8 +120,8 @@ def write_bitlist_to_memory(self, value, addr, num_bytes=1, reverse=False): byte_val = MemoryManager._bitfield_to_byte(sub_bit_list, reverse) self._write_byte(byte_val, addr+i) - def write_bitlist_to_mem_addr(self, value, mem_addr): - self.write_bitlist_to_memory(value, mem_addr[0], mem_addr[1]) + def write_bitlist_to_mem_addr(self, value, mem_addr, reverse=False): + self.write_bitlist_to_memory(value, mem_addr[0], mem_addr[1], reverse) def read_text_from_memory(self, address, num_bytes): """ diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py index d60ace8fe..a7ddd0b6d 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py @@ -59,27 +59,27 @@ def remove_badge(self, badge : Badge): @staticmethod def load_player(mem_manager): - name = mem_manager.read_text_from_memory(PlayerAddress.NAME[0], PlayerAddress.NAME[1]) + name = mem_manager.read_text_from_mem_addr(PlayerAddress.NAME.value) - num_pokemon_in_party = mem_manager.read_hex_from_memory(PlayerAddress.NUM_POKEMON_IN_PARTY[0]) + num_pokemon_in_party = mem_manager.read_hex_from_mem_addr(PlayerAddress.NUM_POKEMON_IN_PARTY.value) - pokemon_in_party = [PokemonId(mem_manager.read_hex_from_memory(PlayerAddress.NUM_POKEMON_IN_PARTY[0]+i+1)) + pokemon_in_party = [PokemonId(mem_manager.read_hex_from_mem_addr(PlayerAddress.NUM_POKEMON_IN_PARTY.add_addr(i+1))) for i in range(num_pokemon_in_party)] - badges = mem_manager.read_bitfield_from_memory(PlayerAddress.BADGES[0]) + badges = mem_manager.read_bitfield_from_mem_addr(PlayerAddress.BADGES.value) - money = mem_manager.read_bcd_from_memory(PlayerAddress.MONEY[0], PlayerAddress.MONEY[1]) + money = mem_manager.read_bcd_from_mem_addr(PlayerAddress.MONEY.value) return Player(name, pokemon_in_party, badges, money) def save_player(self, mem_manager): - mem_manager.write_text_to_memory(self._name, PlayerAddress.NAME[0]) - mem_manager.write_hex_to_memory(self.num_pokemon_in_party, PlayerAddress.NUM_POKEMON_IN_PARTY[0]) + mem_manager.write_text_to_mem_addr(self._name, PlayerAddress.NAME.value) + mem_manager.write_hex_to_mem_addr(self.num_pokemon_in_party, PlayerAddress.NUM_POKEMON_IN_PARTY.value) # TODO: Figure out the loading and unloading of Pokemon in party, as that should be in tandem with # Pokemon class so that data does not get out of sync - mem_manager.write_bitlist_to_memory(PlayerAddress.BADGES[0]) - mem_manager.write_bcd_to_memory(self._money, PlayerAddress.MONEY[0], PlayerAddress.MONEY[1]) + mem_manager.write_bitlist_to_mem_addr(self._badges, PlayerAddress.BADGES.value) + mem_manager.write_bcd_to_mem_addr(self._money, PlayerAddress.MONEY.value) \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokedex.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokedex.py index 9de770c1b..3fbc36106 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokedex.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokedex.py @@ -18,14 +18,14 @@ def __init__(self, self._seen_pokemon = seen_pokemon @staticmethod - def get_pokedex_range_bits(mem_manager, addr, num_bytes): - return mem_manager.read_bitfield_from_memory(addr, num_bytes, reverse=True) + def get_pokedex_range_bits(mem_manager, mem_addr): + return mem_manager.read_bitfield_from_mem_addr(mem_addr, reverse=True) @staticmethod def load_pokedex(mem_manager): - caught_pokemon = Pokedex.get_pokedex_range_bits(mem_manager, POKEDEX_CAUGHT_ADDR_INT[0], num_bytes=POKEDEX_CAUGHT_ADDR_INT[1]) - seen_pokemon = Pokedex.get_pokedex_range_bits(mem_manager, POKEDEX_SEEN_ADDR_INT[0], num_bytes=POKEDEX_SEEN_ADDR_INT[1]) + caught_pokemon = Pokedex.get_pokedex_range_bits(mem_manager, POKEDEX_CAUGHT_ADDR_INT) + seen_pokemon = Pokedex.get_pokedex_range_bits(mem_manager, POKEDEX_SEEN_ADDR_INT) return Pokedex(caught_pokemon, seen_pokemon) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py index ac21bf4e6..0b87b8779 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py @@ -157,8 +157,8 @@ def _load_pokemon_from_address(mem_manager, pokemon_base_address, in_party): it = list(PokemonMemoryOffset)[:-6] for offset_enum in PokemonMemoryOffset: - offset, num_bytes = offset_enum.value[0], offset_enum.value[1] - memory_value = mem_manager.read_hex_from_memory(pokemon_base_address+offset, num_bytes) + offset_addr = offset_enum.add_addr(pokemon_base_address) + memory_value = mem_manager.read_hex_from_mem_addr(offset_addr) pokemon_values.append(memory_value) return Pokemon(*pokemon_values, in_party) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/base.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/base.py index b2f6588bf..70b4cf587 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/base.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/base.py @@ -8,4 +8,5 @@ def __str__(self): def add_addr(self, offset): # Super hacky way to 'add' an offset to an enum, which just # returns a new tuple with the right values + print(self.value) return (self.value[0]+offset, self.value[1]) \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/player.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/player.py index 5aad0ff11..dad4c90ec 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/player.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/player.py @@ -1,4 +1,4 @@ -from base import MemoryAddressEnum +from .base import MemoryAddressEnum class PlayerAddress(MemoryAddressEnum): NAME = (0xD158, 10) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/pokemon.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/pokemon.py index ec449205a..44b6a16f7 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/pokemon.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/pokemon.py @@ -1,6 +1,6 @@ # Pokemon locations in memory from enum import Enum -from base import MemoryAddressEnum +from .base import MemoryAddressEnum class PokemonBaseAddress(Enum): POKEMON_1 = 0xD16B From e65acb9ea1fa61875b0a3fee430400e097ea827c Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Wed, 8 Nov 2023 18:04:44 -0500 Subject: [PATCH 58/74] Fix a few write bugs discovered in Player write testing --- .../game_wrapper_pokemon_gen1/core/mem_manager.py | 14 +++++++------- .../game_wrapper_pokemon_gen1/core/player.py | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py index a3a4d3703..45a9ca46e 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py @@ -24,9 +24,9 @@ def _bitfield_to_byte(bitlist, reverse : bool): if reverse: bitlist.reverse() - bit_str = ''.join(bitlist) + bit_str = ''.join([str(i) for i in bitlist]) - return int(bit_str) + return int(bit_str, 2) @staticmethod def get_character_index(character): @@ -70,7 +70,7 @@ def read_hex_from_mem_addr(self, mem_addr): def write_hex_to_memory(self, value, addr, num_bytes=1): bytes = value.to_bytes(2, byteorder='big') - assert len(bytes) == num_bytes + assert len(bytes) == num_bytes*2 for i, byte in enumerate(bytes): self._write_byte(addr + i, byte) @@ -144,15 +144,15 @@ def read_text_from_memory(self, address, num_bytes): def read_text_from_mem_addr(self, mem_addr): return self.read_text_from_memory(mem_addr[0], mem_addr[1]) - def write_text_to_memory_text(self, text, address, num_bytes=1): + def write_text_to_memory(self, text, address, num_bytes=1): """Sets text at address. Will always add a string terminator (80) at the end. """ - terminated_text = text + STRING_TERMINATOR - # TODO: Check that this isn't an odd-by-one issue - assert terminated_text <= num_bytes + terminated_text = text + '\0' + # TODO: Check that this isn't an off-by-one issue + assert len(terminated_text) <= num_bytes i = 0 for i, chr in enumerate(text): diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py index a7ddd0b6d..4f5905d86 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py @@ -34,7 +34,7 @@ def money(self): @money.setter def money(self, m): # Max money game can store is 999999 - return max(m, 999999) + self._money = min(m, 999999) @property def num_pokemon_in_party(self): @@ -51,10 +51,10 @@ def has_badge(self, badge : Badge): return self._badges[badge.value] == 1 def give_badge(self, badge : Badge): - self._badges[badge.value] == 1 + self._badges[badge.value] = 1 def remove_badge(self, badge : Badge): - self._badges[badge.value] == 0 + self._badges[badge.value] = 0 @staticmethod def load_player(mem_manager): From 91f135598128a24d50863765b3af29bfb6767c2a Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Sun, 3 Dec 2023 21:02:45 -0500 Subject: [PATCH 59/74] Add memory access functions for a variety of common functions --- pyboy/pyboy.py | 100 ++++++++++++++++++++++++++++++++++++++++++++++++- pyboy/utils.py | 5 +++ 2 files changed, 104 insertions(+), 1 deletion(-) diff --git a/pyboy/pyboy.py b/pyboy/pyboy.py index 8798a03c4..44faab84a 100644 --- a/pyboy/pyboy.py +++ b/pyboy/pyboy.py @@ -13,7 +13,7 @@ from pyboy.openai_gym import PyBoyGymEnv from pyboy.openai_gym import enabled as gym_enabled from pyboy.plugins.manager import PluginManager -from pyboy.utils import IntIOWrapper, WindowEvent +from pyboy.utils import IntIOWrapper, WindowEvent, byte_to_bitfield from . import botsupport from .core.mb import Motherboard @@ -322,6 +322,104 @@ def get_memory_value(self, addr): An integer with the value of the memory address """ return self.mb.getitem(addr) + + def read_address_from_memory(self, addr): + """ + Reads two consecutive bytes of the Game Boy's current memory state and returns the values as an address. Meant + to be used on locations that are known to store pointers to other necessary addresses. + + Returns + ------- + int: + An integer with the value of two consecutive bytes in memory + """ + return self.get_memory_value(addr) + self.get_memory_value(addr+1) << 8 + + def read_hex_from_memory(self, addr, num_bytes, byteorder): + """ + Reads consecutive bytes and combines them into a single value. + + Parameters + ---------- + addr : int + Memory address to begin reading from + num_bytes : int + Number of consecutive bytes to read + byte_order: str + Order in which to combine bytes. Options are 'big' and 'little' + + Returns + ------- + int: + An integer value representing the value stored in combined consecutive bytes + """ + bytes = [] + for i in range(num_bytes): + bytes.append(self.get_memory_value(addr + i)) + return int.from_bytes(bytes, byteorder=byteorder) + + def read_bcd_from_memory(self, addr, num_bytes): + """ + Reads consecutive bytes, each as a binary-coded decimal, and returns their combined value. + + Parameters + ---------- + addr : int + Memory address to begin reading from + num_bytes : int + Number of consecutive bytes to read + byte_order: str + Order in which to combine bytes. Options are 'big' and 'little' + + Returns + ------- + int: + An integer value representing the stored binary-coded decimal + """ + byte_str = "" + for i in range(num_bytes): + byte_str += "%x"%self.get_memory_value(addr+i) + return int(byte_str) + + def read_bitfield_from_memory(self, addr, num_bytes): + """ + Reads consecutive bytes, converting each into an array of 0s and 1s representing + bit values and appending them. + + Parameters + ---------- + addr : int + Memory address to begin reading from + num_bytes : int + Number of consecutive bytes to read + + Returns + ------- + [int]: + An array of integers (0 and 1 exclusively), representing whether or not + individual bits are toggled. + """ + bits = [] + for i in range(num_bytes): + bits.extend(byte_to_bitfield(self.get_memory_value(addr+i))) + return bits + + def read_text_from_memory(self, address, num_bytes): + """ + Retrieves a string from a given address. + + Args: + address (int): Address from where to retrieve text from. + cap (int): Maximum expected length of string (default: 16). + """ + text = '' + for i in range(num_bytes): + value = self.get_memory_value(address + i) + if value == 80: + break + text += chr(value - 64) + return text + def set_memory_value(self, addr, value): """ diff --git a/pyboy/utils.py b/pyboy/utils.py index b2348ac4c..52240f39e 100644 --- a/pyboy/utils.py +++ b/pyboy/utils.py @@ -139,6 +139,11 @@ def flatten_list(l): flat_list.append(item) return flat_list +def byte_to_bitfield(n): + # Force bit extension to 10 chars; 2 for '0x' and 8 for the bits + bitlist = [1 if digit=='1' else 0 for digit in format(n, '#010b')[2:]] + + return bitlist ############################################################## # Window Events From bfba88b446e5cc6f72e37833f9224c1cc64ee98f Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Mon, 4 Dec 2023 17:20:58 -0500 Subject: [PATCH 60/74] Add function to get player x/y location --- .../game_wrapper_pokemon_gen1.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py index e57532d1e..0011f1da6 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py @@ -114,4 +114,10 @@ def get_pokedex(self): return Pokedex.load_pokedex(self.mem_manager) def get_player(self): - return Player.load_player(self.mem_manager) \ No newline at end of file + return Player.load_player(self.mem_manager) + + def get_player_location(self): + player_location_x = self.mem_manager.read_hex_from_memory(0xD362, 1) + player_location_y = self.mem_manager.read_hex_from_memory(0xD361, 1) + + return (player_location_x, player_location_y) \ No newline at end of file From a6c5359136a2c80aac12e172f6188e5a80d44fbd Mon Sep 17 00:00:00 2001 From: SnarkAttack Date: Tue, 5 Dec 2023 11:13:36 -0500 Subject: [PATCH 61/74] Add memory access function in game wrapper that uses the memory manager wrapper functions for ease of testing if memory addresses are useful. SHOULD NOT BE PERMANANT --- .../game_wrapper_pokemon_gen1/core/pokemon.py | 80 ++++++++++--------- .../game_wrapper_pokemon_gen1.py | 33 +++++++- 2 files changed, 74 insertions(+), 39 deletions(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py index 0b87b8779..034b8d175 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py @@ -36,104 +36,108 @@ def __init__(self, speed=0, special=0, in_party=False): - self.pokemon_id = PokemonId(pokemon_id) - self.current_hp = current_hp - self.status = status - self.type_1 = type_1 - self.type_2 = type_2 - self.catch_rate = catch_rate - self.moves = [move_1, move_2, move_3, move_4] - self.trainer_id = trainer_id - self.experience = experience + self._pokemon_id = PokemonId(pokemon_id) + self._current_hp = current_hp + self._status = status + self._type_1 = type_1 + self._type_2 = type_2 + self._catch_rate = catch_rate + self._moves = [move_1, move_2, move_3, move_4] + self._trainer_id = trainer_id + self._experience = experience # EV order: HP, Attack, Defense, Speed, Special - self.evs = [hp_ev, attack_ev, defense_ev, speed_ev, special_ev] - self.attack_defense_iv = attack_defense_iv - self.speed_special_iv = speed_special_iv - self.pp_moves = [pp_move_1, pp_move_2, pp_move_3, pp_move_4] - self.level = level if in_party else box_level + self._evs = [hp_ev, attack_ev, defense_ev, speed_ev, special_ev] + self._attack_defense_iv = attack_defense_iv + self._speed_special_iv = speed_special_iv + self._pp_moves = [pp_move_1, pp_move_2, pp_move_3, pp_move_4] + self._level = level if in_party else box_level # Stat order same as EV order - self.stats = [max_hp, attack, defense, speed, special] - self.in_party = in_party + self._stats = [max_hp, attack, defense, speed, special] + self._in_party = in_party @property def name(self): - return Pokemon.get_pokemon_name_from_id(self.pokemon_id) + return Pokemon.get_pokemon_name_from_id(self._pokemon_id) @property def pokedex_num(self): - return Pokemon.get_pokedex_id_from_pokemon_id(self.pokemon_id) + return Pokemon.get_pokedex_id_from_pokemon_id(self._pokemon_id) @property def move_1(self): - return self.moves[0] + return self._moves[0] @property def move_2(self): - return self.moves[1] + return self._moves[1] @property def move_3(self): - return self.moves[2] + return self._moves[2] @property def move_4(self): - return self.moves[3] + return self._moves[3] @property def pp_move_1(self): - return self.pp_moves[0] + return self._pp_moves[0] @property def pp_move_2(self): - return self.pp_moves[1] + return self._pp_moves[1] @property def pp_move_3(self): - return self.pp_moves[2] + return self._pp_moves[2] @property def pp_move_4(self): - return self.pp_moves[3] + return self._pp_moves[3] @property def hp_ev(self): - return self.evs[0] + return self._evs[0] @property def attack_ev(self): - return self.evs[1] + return self._evs[1] @property def defense_ev(self): - return self.evs[2] + return self._evs[2] @property def speed_ev(self): - return self.evs[3] + return self._evs[3] @property def special_ev(self): - return self.evs[4] + return self._evs[4] @property def max_hp(self): - return self.stats[0] + return self._stats[0] @property def attack(self): - return self.stats[1] + return self._stats[1] @property def defense(self): - return self.stats[2] + return self._stats[2] @property def speed(self): - return self.stats[3] + return self._stats[3] @property def special(self): - return self.stats[4] + return self._stats[4] + + @property + def curr_hp_percent(self): + return self._current_hp / self.max_hp @staticmethod def get_pokemon_name_from_id(pokemon_id): @@ -172,8 +176,8 @@ def load_pokemon_from_party(cls, mem_manager, party_location): def _generate_move_str(self): s = f"Moves:\n" - for i, move_id in enumerate(self.moves): - s += f"\t{Move.get_name_from_id(move_id)} ({self.pp_moves[i]}/)\n" + for i, move_id in enumerate(self._moves): + s += f"\t{Move.get_name_from_id(move_id)} ({self._pp_moves[i]}/)\n" return s diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py index e57532d1e..ca7cfd94b 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py @@ -114,4 +114,35 @@ def get_pokedex(self): return Pokedex.load_pokedex(self.mem_manager) def get_player(self): - return Player.load_player(self.mem_manager) \ No newline at end of file + return Player.load_player(self.mem_manager) + + def get_player_location(self): + player_sprite_y = self.mem_manager.read_hex_from_memory(0xD361, 1) + player_sprite_x = self.mem_manager.read_hex_from_memory(0xD362, 1) + + return (player_sprite_x, player_sprite_y) + + ''' + WARNING + + The following functions are NOT meant to be used consistently. They exist only as + a way to call the heper memory access functions for testing memory fields. They + WILL BE REMOVED. Ideally, some form of the memory access functions will appear in + PyBoy proper, but alternatively and data accesses made with these functions should + be turned into a named function in the game wrapper. If you find yourself using these + functions consistenly, please open up an issue at https://github.com/SnarkAttack/PyBoy + and indicate the memory addresses you are accessing and their use so that a named function + can be created. If you need those memory values, other people might too. + ''' + + def memory_read(self, address, num_bytes, read_type): + if read_type == 'hex': + self.mem_manager.read_hex_from_memory(address, num_bytes) + elif read_type == 'address': + self.mem_manager.read_address_from_memory(address, num_bytes) + elif read_type == 'bcd': + self.mem_manager.read_bcd_from_memory(address, num_bytes) + elif read_type == 'text': + self.mem_manager.read_text_from_memory(address, num_bytes) + else: + raise ValueError(f"{read_type} is not a valid read type") \ No newline at end of file From 19d19055194fd0397b2cfc560dfe520974df36d2 Mon Sep 17 00:00:00 2001 From: SnarkAttack Date: Tue, 5 Dec 2023 11:52:32 -0500 Subject: [PATCH 62/74] Add GameState object to track general game info --- .../core/game_state.py | 19 +++++++++++++++++++ .../data/memory_addrs/game_state.py | 4 ++++ .../game_wrapper_pokemon_gen1.py | 14 +++++++++----- 3 files changed, 32 insertions(+), 5 deletions(-) create mode 100644 pyboy/plugins/game_wrapper_pokemon_gen1/core/game_state.py create mode 100644 pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/game_state.py diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/game_state.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/game_state.py new file mode 100644 index 000000000..323e7e2df --- /dev/null +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/game_state.py @@ -0,0 +1,19 @@ +from ..data.memory_addrs.game_state import GameStateAddress + +class GameState(): + + def __init__(self, + battle_type + ): + + self._battle_type = battle_type + + def is_in_battle(self): + return self._battle_type == 0 + + @staticmethod + def load_game_state(mem_manager): + + battle_type = mem_manager.read_hex_from_mem_address(GameStateAddress.BATTLE_TYPE.value) + + return GameState(battle_type) \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/game_state.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/game_state.py new file mode 100644 index 000000000..2031c76aa --- /dev/null +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/game_state.py @@ -0,0 +1,4 @@ +from .base import MemoryAddressEnum + +class GameStateAddress(MemoryAddressEnum): + BATTLE_TYPE = (0xD057, 1) \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py index ca7cfd94b..b26a1ad63 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py @@ -17,6 +17,7 @@ from .core.pokemon import Pokemon from .core.player import Player from .core.mem_manager import MemoryManager +from .core.game_state import GameState PKMN_SIZE = 0x2C BYTE_ORDER = 'big' @@ -122,6 +123,9 @@ def get_player_location(self): return (player_sprite_x, player_sprite_y) + def get_game_state(self): + return GameState.load_game_state(self.mem_manager) + ''' WARNING @@ -135,14 +139,14 @@ def get_player_location(self): can be created. If you need those memory values, other people might too. ''' - def memory_read(self, address, num_bytes, read_type): + def read_memory(self, address, num_bytes, read_type): if read_type == 'hex': - self.mem_manager.read_hex_from_memory(address, num_bytes) + return self.mem_manager.read_hex_from_memory(address, num_bytes) elif read_type == 'address': - self.mem_manager.read_address_from_memory(address, num_bytes) + return self.mem_manager.read_address_from_memory(address, num_bytes) elif read_type == 'bcd': - self.mem_manager.read_bcd_from_memory(address, num_bytes) + return self.mem_manager.read_bcd_from_memory(address, num_bytes) elif read_type == 'text': - self.mem_manager.read_text_from_memory(address, num_bytes) + return self.mem_manager.read_text_from_memory(address, num_bytes) else: raise ValueError(f"{read_type} is not a valid read type") \ No newline at end of file From bc2c544465b06a8b2837b10c2668cf68f9373908 Mon Sep 17 00:00:00 2001 From: SnarkAttack Date: Tue, 5 Dec 2023 12:29:59 -0500 Subject: [PATCH 63/74] Fix check on game_state.is_in_battle (was returning opposite of desired) --- .../plugins/game_wrapper_pokemon_gen1/core/game_state.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/game_state.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/game_state.py index 323e7e2df..6552a1248 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/game_state.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/game_state.py @@ -9,11 +9,15 @@ def __init__(self, self._battle_type = battle_type def is_in_battle(self): - return self._battle_type == 0 + return self._battle_type != 0 + + @property + def battle_type(self): + return self._battle_type @staticmethod def load_game_state(mem_manager): - battle_type = mem_manager.read_hex_from_mem_address(GameStateAddress.BATTLE_TYPE.value) + battle_type = mem_manager.read_hex_from_mem_addr(GameStateAddress.BATTLE_TYPE.value) return GameState(battle_type) \ No newline at end of file From 2486aaded3bf5d914362804ed9b48229c885ef46 Mon Sep 17 00:00:00 2001 From: SnarkAttack Date: Tue, 5 Dec 2023 13:39:35 -0500 Subject: [PATCH 64/74] Rewrite memory address enums so they are now a class and also track in what form the memory is encoded at that address, then added overarching read and write functions that use appropriate memory type functions --- .../game_wrapper_pokemon_gen1/core/battle.py | 53 +++++++++++++++ .../core/game_state.py | 2 +- .../core/mem_manager.py | 64 +++++++++++-------- .../game_wrapper_pokemon_gen1/core/player.py | 18 +++--- .../game_wrapper_pokemon_gen1/core/pokedex.py | 3 +- .../game_wrapper_pokemon_gen1/core/pokemon.py | 4 +- .../data/memory_addrs/base.py | 32 ++++++++-- .../data/memory_addrs/battle.py | 48 ++++++++++++++ .../data/memory_addrs/game_state.py | 7 +- .../data/memory_addrs/player.py | 13 ++-- .../data/memory_addrs/pokemon.py | 64 +++++++++---------- 11 files changed, 224 insertions(+), 84 deletions(-) create mode 100644 pyboy/plugins/game_wrapper_pokemon_gen1/core/battle.py create mode 100644 pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/battle.py diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/battle.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/battle.py new file mode 100644 index 000000000..7dc15a412 --- /dev/null +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/battle.py @@ -0,0 +1,53 @@ +from ..data.memory_addrs.battle import Battle + +class Battle(): + + def __init__(self, mem_addrs_to_track): + + self._mem_addrs_to_track = mem_addrs_to_track + + # ENEMY_MOVE_ID = (0xCFCC, 1) + # ENEMY_MOVE_EFFECT = (0xCFCD, 1) + # ENEMY_MOVE_POWER = (0xCFCE, 1) + # ENEMY_MOVE_TYPE = (0xCFCF, 1) + # ENEMY_MOVE_ACCURACY = (0xCFD0, 1) + # ENEMY_MOVE_MAX_PP = (0xCFD1, 1) + # PLAYER_MOVE_ID = (0xCFD2, 1) + # PLAYER_MOVE_EFFECT = (0xCFD3, 1) + # PLAYER_MOVE_POWER = (0xCFD4, 1) + # PLAYER_MOVE_TYPE = (0xCFD5, 1) + # PLAYER_MOVE_ACCURACY = (0xCFD6, 1) + # PLAYER_MOVE_MAX_PP = (0xCFD7, 1) + # ENEMY_POKEMON_ID = (0xCFD8, 1) + # PLAYER_POKEMON_ID = (0xCFD9, 1) + # ENEMY_NAME = (0xCFDA, 10) + # # This seems to be a repat? + # # ENEMY_POKEMON_ID = (0xCFE5, 1) + # ENEMY_HP = (0xCFE6, 2) + # ENEMY_LEVEL = (0xCFE8, 1) + # ENEMY_STATUS = (0xCFE9, 1) + # ENEMY_TYPE_1 = (0xCFEA, 1) + # ENEMY_TPYE_2 = (0xCFEB, 1) + # # ENEMY_CATCH_RATE_UNUSED only checked by move Transform + # ENEMY_CATCH_RATE_UNUSED = (0xCFEC, 1) + # ENEMY_MOVE_1 = (0xCFED, 1) + # ENEMY_MOVE_2 = (0xCFEE, 1) + # ENEMY_MOVE_3 = (0xCFEF, 1) + # ENEMY_MOVE_4 = (0xCFF0, 1) + # ENEMY_ATT_DEF_DVS = (0xCFF1, 1) + # ENEMY_SPEED_SPEC_DVS = (0xCFF2, 1) + # # Another repeat? + # # ENEMY_LEVEL = (0xCFEC) + # ENEMY_MAX_HP = (0xCFF4, 2) + # ENEMY_ATTACK = (0xCFF6, 2) + # ENEMY_DEFENSE = (0xCFF8, 2) + # ENEMY_SPEED = (0xCFFA, 2) + # ENEMY_SPECIAL = (0xCFFC, 2) + # ENEMY_MOVE_PP_1 = (0xCFFF, 1) + # ENEMY_MOVE_PP_2 = (0xCFFF, 1) + # ENEMY_MOVE_PP_3 = (0xD000, 1) + # EMENY_MOVE_PP_4 = (0xD001, 1) + # ENEMY_BASE_STATS = (0xD002, 5) + # ENEMY_CATCH_RATE = (0xD007, 1) + # ENEMY_BASE_EXP = (0xD008, 1) + # TYPE_OF_BATTLE = (0xD057, 1) \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/game_state.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/game_state.py index 6552a1248..8e1de7745 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/game_state.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/game_state.py @@ -18,6 +18,6 @@ def battle_type(self): @staticmethod def load_game_state(mem_manager): - battle_type = mem_manager.read_hex_from_mem_addr(GameStateAddress.BATTLE_TYPE.value) + battle_type = mem_manager.read_memory_address(GameStateAddress.BATTLE_TYPE) return GameState(battle_type) \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py index 45a9ca46e..c8aca3ddb 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py @@ -1,3 +1,5 @@ +from data.memory_addrs.base import MemoryAddress, MemoryAddressType + STRING_TERMINATOR = 80 ASCII_DELTA = 63 @@ -64,28 +66,19 @@ def read_hex_from_memory(self, addr, num_bytes=1): # Do not believe there is ever a case where we would # need to read this in little endian for Pokemon gen 1 return int.from_bytes(bytes, byteorder='big') - - def read_hex_from_mem_addr(self, mem_addr): - return self.read_hex_from_memory(mem_addr[0], mem_addr[1]) - + def write_hex_to_memory(self, value, addr, num_bytes=1): bytes = value.to_bytes(2, byteorder='big') assert len(bytes) == num_bytes*2 for i, byte in enumerate(bytes): self._write_byte(addr + i, byte) - def write_hex_to_mem_addr(self, value, mem_addr): - self.write_hex_to_memory(value, mem_addr[0], mem_addr[1]) - def read_bcd_from_memory(self, addr, num_bytes=1): byte_str = "" for i in range(num_bytes): byte_str += "%x"%self._read_byte(addr+i) return int(byte_str) - - def read_bcd_from_mem_addr(self, mem_addr): - return self.read_bcd_from_memory(mem_addr[0], mem_addr[1]) - + def write_bcd_to_memory(self, value, addr, num_bytes=1): val_str = str(value) assert len(val_str) <= num_bytes*2 @@ -95,18 +88,12 @@ def write_bcd_to_memory(self, value, addr, num_bytes=1): sub_val = int(padded_val[i*2:(i*2)+2], 16) self._write_byte(sub_val, addr+i) - def write_bcd_to_mem_addr(self, value, mem_addr): - self.write_bcd_to_memory(value, mem_addr[0], mem_addr[1]) - def read_bitfield_from_memory(self, addr, num_bytes=1, reverse=False): bits = [] for i in range(num_bytes): bits.extend(MemoryManager._byte_to_bitfield(self._read_byte(addr+i), reverse)) return bits - def read_bitfield_from_mem_addr(self, mem_addr, reverse=False): - return self.read_bitfield_from_memory(mem_addr[0], mem_addr[1], reverse) - def write_bitlist_to_memory(self, value, addr, num_bytes=1, reverse=False): # TODO: This check might be too restrictive @@ -120,9 +107,6 @@ def write_bitlist_to_memory(self, value, addr, num_bytes=1, reverse=False): byte_val = MemoryManager._bitfield_to_byte(sub_bit_list, reverse) self._write_byte(byte_val, addr+i) - def write_bitlist_to_mem_addr(self, value, mem_addr, reverse=False): - self.write_bitlist_to_memory(value, mem_addr[0], mem_addr[1], reverse) - def read_text_from_memory(self, address, num_bytes): """ Retrieves a string from a given address. @@ -141,9 +125,6 @@ def read_text_from_memory(self, address, num_bytes): text += chr(value - ASCII_DELTA) return text - def read_text_from_mem_addr(self, mem_addr): - return self.read_text_from_memory(mem_addr[0], mem_addr[1]) - def write_text_to_memory(self, text, address, num_bytes=1): """Sets text at address. @@ -158,5 +139,38 @@ def write_text_to_memory(self, text, address, num_bytes=1): for i, chr in enumerate(text): self.pyboy.set_memory_value(address + i, MemoryManager.get_character_index(chr)) - def write_text_to_mem_addr(self, text, mem_addr): - self.write_text_to_memory(text, mem_addr[0], mem_addr[1]) \ No newline at end of file + def read_memory_address(self, mem_addr_enum): + mem_addr = mem_addr_enum.value + if mem_addr.memory_type == MemoryAddressType.HEX: + mem_func = self.read_hex_from_memory + elif mem_addr.memory_type == MemoryAddressType.ADDRESS: + mem_func = self.read_address_from_memory + elif mem_addr.memory_type == MemoryAddressType.BCD: + mem_func = self.read_bcd_from_memory + elif mem_addr.memory_type == MemoryAddressType.BITFIELD: + mem_func = self.read_bitfield_from_memory + elif mem_addr.memory_type == MemoryAddressType.TEXT: + mem_func = self.read_text_from_memory + else: + raise ValueError(f"{mem_addr.memory_type} is not a valid memory type") + + return mem_func(mem_addr.address, mem_addr.num_bytes) + + def write_memory_address(self, mem_addr_enum): + mem_addr = mem_addr_enum.value + if mem_addr.memory_type == MemoryAddressType.HEX: + mem_func = self.write_hex_to_memory + elif mem_addr.memory_type == MemoryAddressType.ADDRESS: + #mem_func = self.write_add + pass + elif mem_addr.memory_type == MemoryAddressType.BCD: + mem_func = self.write_bcd_to_memory + elif mem_addr.memory_type == MemoryAddressType.BITFIELD: + mem_func = self.write_bitlist_to_memory + elif mem_addr.memory_type == MemoryAddressType.TEXT: + mem_func = self.write_text_to_memory + else: + raise ValueError(f"{mem_addr.memory_type} is not a valid memory type") + + return mem_func(mem_addr.address, mem_addr.num_bytes) + \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py index 4f5905d86..fd28f627d 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py @@ -59,27 +59,27 @@ def remove_badge(self, badge : Badge): @staticmethod def load_player(mem_manager): - name = mem_manager.read_text_from_mem_addr(PlayerAddress.NAME.value) + name = mem_manager.read_memory_address(PlayerAddress.NAME) - num_pokemon_in_party = mem_manager.read_hex_from_mem_addr(PlayerAddress.NUM_POKEMON_IN_PARTY.value) + num_pokemon_in_party = mem_manager.read_memory_address(PlayerAddress.NUM_POKEMON_IN_PARTY) - pokemon_in_party = [PokemonId(mem_manager.read_hex_from_mem_addr(PlayerAddress.NUM_POKEMON_IN_PARTY.add_addr(i+1))) + pokemon_in_party = [PokemonId(mem_manager.read_memory_address(PlayerAddress.NUM_POKEMON_IN_PARTY.add_addr(i+1))) for i in range(num_pokemon_in_party)] - badges = mem_manager.read_bitfield_from_mem_addr(PlayerAddress.BADGES.value) + badges = mem_manager.read_memory_address(PlayerAddress.BADGES) - money = mem_manager.read_bcd_from_mem_addr(PlayerAddress.MONEY.value) + money = mem_manager.read_memory_address(PlayerAddress.MONEY) return Player(name, pokemon_in_party, badges, money) def save_player(self, mem_manager): - mem_manager.write_text_to_mem_addr(self._name, PlayerAddress.NAME.value) - mem_manager.write_hex_to_mem_addr(self.num_pokemon_in_party, PlayerAddress.NUM_POKEMON_IN_PARTY.value) + mem_manager.write_memory_address(self._name, PlayerAddress.NAME) + mem_manager.write_memory_address(self.num_pokemon_in_party, PlayerAddress.NUM_POKEMON_IN_PARTY) # TODO: Figure out the loading and unloading of Pokemon in party, as that should be in tandem with # Pokemon class so that data does not get out of sync - mem_manager.write_bitlist_to_mem_addr(self._badges, PlayerAddress.BADGES.value) - mem_manager.write_bcd_to_mem_addr(self._money, PlayerAddress.MONEY.value) + mem_manager.write_memory_address(self._badges, PlayerAddress.BADGES) + mem_manager.write_memory_address(self._money, PlayerAddress.MONEY) \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokedex.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokedex.py index 3fbc36106..ee512b05b 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokedex.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokedex.py @@ -19,8 +19,7 @@ def __init__(self, @staticmethod def get_pokedex_range_bits(mem_manager, mem_addr): - return mem_manager.read_bitfield_from_mem_addr(mem_addr, reverse=True) - + return mem_manager.read_memory_address(mem_addr, reverse=True) @staticmethod def load_pokedex(mem_manager): diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py index 034b8d175..4c486c34c 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py @@ -160,9 +160,9 @@ def _load_pokemon_from_address(mem_manager, pokemon_base_address, in_party): # level field or any of its stats saved in memory it = list(PokemonMemoryOffset)[:-6] - for offset_enum in PokemonMemoryOffset: + for offset_enum in PokemonMemoryOffset.values(): offset_addr = offset_enum.add_addr(pokemon_base_address) - memory_value = mem_manager.read_hex_from_mem_addr(offset_addr) + memory_value = mem_manager.read_memory_address(offset_addr) pokemon_values.append(memory_value) return Pokemon(*pokemon_values, in_party) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/base.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/base.py index 70b4cf587..ff65f606b 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/base.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/base.py @@ -1,12 +1,36 @@ from enum import Enum -class MemoryAddressEnum(Enum): +class MemoryAddress(): + + def __init__(self, address, num_bytes, memory_type): + self._address = address + self._num_bytes = num_bytes + self._memory_type = memory_type + + @property + def address(self): + return self._address + + @property + def num_bytes(self): + return self._num_bytes + + @property + def memory_type(self): + return self._memory_type def __str__(self): - return f"Memory address: {self.value[0]}: Length: {self.value[1]}" + return f"Memory address: {self._address}: Length: {self._num_bytes}, memory_addr_type: {self._memory_type}" def add_addr(self, offset): # Super hacky way to 'add' an offset to an enum, which just # returns a new tuple with the right values - print(self.value) - return (self.value[0]+offset, self.value[1]) \ No newline at end of file + return MemoryAddress(self.address+offset, self.num_bytes, self.memory_type) + + +class MemoryAddressType(Enum): + HEX = 0 + ADDRESS = 1 + BCD = 2 + BITFIELD = 3 + TEXT = 4 \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/battle.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/battle.py new file mode 100644 index 000000000..3bb4f7d3b --- /dev/null +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/battle.py @@ -0,0 +1,48 @@ +from .base import MemoryAddressEnum, MemoryAddressType + +class InternationalBattleAddress(MemoryAddressEnum): + ENEMY_MOVE_ID = (0xCFCC, 1, MemoryAddressType.HEX) + ENEMY_MOVE_EFFECT = (0xCFCD, 1, MemoryAddressType.HEX) + ENEMY_MOVE_POWER = (0xCFCE, 1, MemoryAddressType.HEX) + ENEMY_MOVE_TYPE = (0xCFCF, 1) + ENEMY_MOVE_ACCURACY = (0xCFD0, 1) + ENEMY_MOVE_MAX_PP = (0xCFD1, 1) + PLAYER_MOVE_ID = (0xCFD2, 1) + PLAYER_MOVE_EFFECT = (0xCFD3, 1) + PLAYER_MOVE_POWER = (0xCFD4, 1) + PLAYER_MOVE_TYPE = (0xCFD5, 1) + PLAYER_MOVE_ACCURACY = (0xCFD6, 1) + PLAYER_MOVE_MAX_PP = (0xCFD7, 1) + ENEMY_POKEMON_ID = (0xCFD8, 1) + PLAYER_POKEMON_ID = (0xCFD9, 1) + ENEMY_NAME = (0xCFDA, 10) + # This seems to be a repat? + # ENEMY_POKEMON_ID = (0xCFE5, 1) + ENEMY_HP = (0xCFE6, 2) + ENEMY_LEVEL = (0xCFE8, 1) + ENEMY_STATUS = (0xCFE9, 1) + ENEMY_TYPE_1 = (0xCFEA, 1) + ENEMY_TPYE_2 = (0xCFEB, 1) + # ENEMY_CATCH_RATE_UNUSED only checked by move Transform + ENEMY_CATCH_RATE_UNUSED = (0xCFEC, 1) + ENEMY_MOVE_1 = (0xCFED, 1) + ENEMY_MOVE_2 = (0xCFEE, 1) + ENEMY_MOVE_3 = (0xCFEF, 1) + ENEMY_MOVE_4 = (0xCFF0, 1) + ENEMY_ATT_DEF_DVS = (0xCFF1, 1) + ENEMY_SPEED_SPEC_DVS = (0xCFF2, 1) + # Another repeat? + # ENEMY_LEVEL = (0xCFEC) + ENEMY_MAX_HP = (0xCFF4, 2) + ENEMY_ATTACK = (0xCFF6, 2) + ENEMY_DEFENSE = (0xCFF8, 2) + ENEMY_SPEED = (0xCFFA, 2) + ENEMY_SPECIAL = (0xCFFC, 2) + ENEMY_MOVE_PP_1 = (0xCFFF, 1) + ENEMY_MOVE_PP_2 = (0xCFFF, 1) + ENEMY_MOVE_PP_3 = (0xD000, 1) + EMENY_MOVE_PP_4 = (0xD001, 1) + ENEMY_BASE_STATS = (0xD002, 5) + ENEMY_CATCH_RATE = (0xD007, 1) + ENEMY_BASE_EXP = (0xD008, 1) + TYPE_OF_BATTLE = (0xD057, 1) \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/game_state.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/game_state.py index 2031c76aa..d549023c7 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/game_state.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/game_state.py @@ -1,4 +1,5 @@ -from .base import MemoryAddressEnum +from enum import Enum +from .base import MemoryAddress, MemoryAddressType -class GameStateAddress(MemoryAddressEnum): - BATTLE_TYPE = (0xD057, 1) \ No newline at end of file +class GameStateAddress(Enum): + BATTLE_TYPE = (0xD057, 1, MemoryAddressType.HEX) \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/player.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/player.py index dad4c90ec..5ff245f3c 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/player.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/player.py @@ -1,7 +1,8 @@ -from .base import MemoryAddressEnum +from enum import Enum +from .base import MemoryAddress, MemoryAddressType -class PlayerAddress(MemoryAddressEnum): - NAME = (0xD158, 10) - NUM_POKEMON_IN_PARTY = (0xD163, 1) - BADGES = (0xD356, 1) - MONEY = (0xD347, 3) \ No newline at end of file +class PlayerAddress(Enum): + NAME = MemoryAddress(0xD158, 10, MemoryAddressType.TEXT) + NUM_POKEMON_IN_PARTY = MemoryAddress(0xD163, 1, MemoryAddressType.HEX) + BADGES = MemoryAddress(0xD356, 1, MemoryAddressType.HEX) + MONEY = MemoryAddress(0xD347, 3, MemoryAddressType.BCD) \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/pokemon.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/pokemon.py index 44b6a16f7..4bdc2aaf7 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/pokemon.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/pokemon.py @@ -1,6 +1,6 @@ # Pokemon locations in memory from enum import Enum -from .base import MemoryAddressEnum +from .base import MemoryAddress, MemoryAddressType class PokemonBaseAddress(Enum): POKEMON_1 = 0xD16B @@ -12,34 +12,34 @@ class PokemonBaseAddress(Enum): # Offsets for Pokemon data access # Structure is (offset, num bytes) -class PokemonMemoryOffset(MemoryAddressEnum): - ID = (0x0, 1) - CURRENT_HP = (0x1, 2) - BOX_LEVEL = (0x3, 1) - STATUS = (0x4, 1) - TYPE_1 = (0x5, 1) - TYPE_2 = (0x6, 1) - CATCH_RATE = (0x7, 1) - MOVE_1 = (0x8, 1) - MOVE_2 = (0x9, 1) - MOVE_3 = (0xA, 1) - MOVE_4 = (0xB, 1) - TRAINER_ID = (0xC, 2) - EXPERIENCE = (0xE, 3) - HP_EV = (0x11, 2) - ATTACK_EV = (0x13, 2) - DEFENSE_EV = (0x15, 2) - SPEED_EV = (0x17, 2) - SPECIAL_EV = (0x19, 2) - ATTACK_DEFENSE_IV = (0x1B, 1) - SPEED_SPECIAL_IV = (0x1C, 1) - PP_MOVE_1 = (0x1D, 1) - PP_MOVE_2 = (0x1E, 1) - PP_MOVE_3 = (0x1F, 1) - PP_MOVE_4 = (0x20, 1) - LEVEL = (0x21, 1) - MAX_HP = (0x22, 2) - ATTACK = (0x24, 2) - DEFENSE = (0x26, 2) - SPEED = (0x28, 2) - SPECIAL = (0x2A, 2) \ No newline at end of file +class PokemonMemoryOffset(Enum): + ID = MemoryAddress(0x0, 1, MemoryAddressType.HEX) + CURRENT_HP = MemoryAddress(0x1, 2, MemoryAddressType.HEX) + BOX_LEVEL = MemoryAddress(0x3, 1, MemoryAddressType.HEX) + STATUS = MemoryAddress(0x4, 1, MemoryAddressType.HEX) + TYPE_1 = MemoryAddress(0x5, 1, MemoryAddressType.HEX) + TYPE_2 = MemoryAddress(0x6, 1, MemoryAddressType.HEX) + CATCH_RATE = MemoryAddress(0x7, 1, MemoryAddressType.HEX) + MOVE_1 = MemoryAddress(0x8, 1, MemoryAddressType.HEX) + MOVE_2 = MemoryAddress(0x9, 1, MemoryAddressType.HEX) + MOVE_3 = MemoryAddress(0xA, 1, MemoryAddressType.HEX) + MOVE_4 = MemoryAddress(0xB, 1, MemoryAddressType.HEX) + TRAINER_ID = MemoryAddress(0xC, 2, MemoryAddressType.HEX) + EXPERIENCE = MemoryAddress(0xE, 3, MemoryAddressType.HEX) + HP_EV = MemoryAddress(0x11, 2, MemoryAddressType.HEX) + ATTACK_EV = MemoryAddress(0x13, 2, MemoryAddressType.HEX) + DEFENSE_EV = MemoryAddress(0x15, 2, MemoryAddressType.HEX) + SPEED_EV = MemoryAddress(0x17, 2, MemoryAddressType.HEX) + SPECIAL_EV = MemoryAddress(0x19, 2, MemoryAddressType.HEX) + ATTACK_DEFENSE_IV = MemoryAddress(0x1B, 1, MemoryAddressType.HEX) + SPEED_SPECIAL_IV = MemoryAddress(0x1C, 1, MemoryAddressType.HEX) + PP_MOVE_1 = MemoryAddress(0x1D, 1, MemoryAddressType.HEX) + PP_MOVE_2 = MemoryAddress(0x1E, 1, MemoryAddressType.HEX) + PP_MOVE_3 = MemoryAddress(0x1F, 1, MemoryAddressType.HEX) + PP_MOVE_4 = MemoryAddress(0x20, 1, MemoryAddressType.HEX) + LEVEL = MemoryAddress(0x21, 1, MemoryAddressType.HEX) + MAX_HP = MemoryAddress(0x22, 2, MemoryAddressType.HEX) + ATTACK = MemoryAddress(0x24, 2, MemoryAddressType.HEX) + DEFENSE = MemoryAddress(0x26, 2, MemoryAddressType.HEX) + SPEED = MemoryAddress(0x28, 2, MemoryAddressType.HEX) + SPECIAL = MemoryAddress(0x2A, 2, MemoryAddressType.HEX) \ No newline at end of file From 759d6168caac40d3fa8a55f212cfc3f6b0f3fff8 Mon Sep 17 00:00:00 2001 From: SnarkAttack Date: Tue, 5 Dec 2023 14:40:14 -0500 Subject: [PATCH 65/74] Allow read and write super calls tot ake in straight MemoryAddress object OR enum with MemoryAddress object as value --- .../game_wrapper_pokemon_gen1/core/mem_manager.py | 13 ++++++++----- .../game_wrapper_pokemon_gen1/core/pokemon.py | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py index c8aca3ddb..09a2ef8cf 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py @@ -1,4 +1,5 @@ -from data.memory_addrs.base import MemoryAddress, MemoryAddressType +from enum import Enum +from ..data.memory_addrs.base import MemoryAddress, MemoryAddressType STRING_TERMINATOR = 80 ASCII_DELTA = 63 @@ -139,8 +140,9 @@ def write_text_to_memory(self, text, address, num_bytes=1): for i, chr in enumerate(text): self.pyboy.set_memory_value(address + i, MemoryManager.get_character_index(chr)) - def read_memory_address(self, mem_addr_enum): - mem_addr = mem_addr_enum.value + def read_memory_address(self, mem_addr): + if isinstance(mem_addr, Enum): + mem_addr = mem_addr.value if mem_addr.memory_type == MemoryAddressType.HEX: mem_func = self.read_hex_from_memory elif mem_addr.memory_type == MemoryAddressType.ADDRESS: @@ -156,8 +158,9 @@ def read_memory_address(self, mem_addr_enum): return mem_func(mem_addr.address, mem_addr.num_bytes) - def write_memory_address(self, mem_addr_enum): - mem_addr = mem_addr_enum.value + def write_memory_address(self, mem_addr): + if isinstance(mem_addr, Enum): + mem_addr = mem_addr.value if mem_addr.memory_type == MemoryAddressType.HEX: mem_func = self.write_hex_to_memory elif mem_addr.memory_type == MemoryAddressType.ADDRESS: diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py index 4c486c34c..8fb26e61d 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py @@ -160,7 +160,7 @@ def _load_pokemon_from_address(mem_manager, pokemon_base_address, in_party): # level field or any of its stats saved in memory it = list(PokemonMemoryOffset)[:-6] - for offset_enum in PokemonMemoryOffset.values(): + for offset_enum in [e.value for e in PokemonMemoryOffset]: offset_addr = offset_enum.add_addr(pokemon_base_address) memory_value = mem_manager.read_memory_address(offset_addr) pokemon_values.append(memory_value) From 3027a8eea3fc6557eec39fe888ec62f09f2a3d78 Mon Sep 17 00:00:00 2001 From: SnarkAttack Date: Tue, 5 Dec 2023 16:44:50 -0500 Subject: [PATCH 66/74] Convert previous objects that stored representations of data in memory into MemoryObjects, which only store that data requested for more efficient loads/stores --- .../game_wrapper_pokemon_gen1/core/battle.py | 57 +---- .../core/memory_object.py | 22 ++ .../game_wrapper_pokemon_gen1/core/pokemon.py | 219 +++++++----------- .../data/memory_addrs/base.py | 36 ++- .../data/memory_addrs/battle.py | 135 +++++++---- .../data/memory_addrs/pokemon.py | 99 +++++--- 6 files changed, 300 insertions(+), 268 deletions(-) create mode 100644 pyboy/plugins/game_wrapper_pokemon_gen1/core/memory_object.py diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/battle.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/battle.py index 7dc15a412..25d612976 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/battle.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/battle.py @@ -1,53 +1,10 @@ -from ..data.memory_addrs.battle import Battle +from .memory_object import MemoryObject +from ..data.memory_addrs.battle import BattleAddress, BATTLE_ADDRESS_LOOKUP -class Battle(): +class Battle(MemoryObject): - def __init__(self, mem_addrs_to_track): + _enum = BattleAddress + _lookup = BATTLE_ADDRESS_LOOKUP - self._mem_addrs_to_track = mem_addrs_to_track - - # ENEMY_MOVE_ID = (0xCFCC, 1) - # ENEMY_MOVE_EFFECT = (0xCFCD, 1) - # ENEMY_MOVE_POWER = (0xCFCE, 1) - # ENEMY_MOVE_TYPE = (0xCFCF, 1) - # ENEMY_MOVE_ACCURACY = (0xCFD0, 1) - # ENEMY_MOVE_MAX_PP = (0xCFD1, 1) - # PLAYER_MOVE_ID = (0xCFD2, 1) - # PLAYER_MOVE_EFFECT = (0xCFD3, 1) - # PLAYER_MOVE_POWER = (0xCFD4, 1) - # PLAYER_MOVE_TYPE = (0xCFD5, 1) - # PLAYER_MOVE_ACCURACY = (0xCFD6, 1) - # PLAYER_MOVE_MAX_PP = (0xCFD7, 1) - # ENEMY_POKEMON_ID = (0xCFD8, 1) - # PLAYER_POKEMON_ID = (0xCFD9, 1) - # ENEMY_NAME = (0xCFDA, 10) - # # This seems to be a repat? - # # ENEMY_POKEMON_ID = (0xCFE5, 1) - # ENEMY_HP = (0xCFE6, 2) - # ENEMY_LEVEL = (0xCFE8, 1) - # ENEMY_STATUS = (0xCFE9, 1) - # ENEMY_TYPE_1 = (0xCFEA, 1) - # ENEMY_TPYE_2 = (0xCFEB, 1) - # # ENEMY_CATCH_RATE_UNUSED only checked by move Transform - # ENEMY_CATCH_RATE_UNUSED = (0xCFEC, 1) - # ENEMY_MOVE_1 = (0xCFED, 1) - # ENEMY_MOVE_2 = (0xCFEE, 1) - # ENEMY_MOVE_3 = (0xCFEF, 1) - # ENEMY_MOVE_4 = (0xCFF0, 1) - # ENEMY_ATT_DEF_DVS = (0xCFF1, 1) - # ENEMY_SPEED_SPEC_DVS = (0xCFF2, 1) - # # Another repeat? - # # ENEMY_LEVEL = (0xCFEC) - # ENEMY_MAX_HP = (0xCFF4, 2) - # ENEMY_ATTACK = (0xCFF6, 2) - # ENEMY_DEFENSE = (0xCFF8, 2) - # ENEMY_SPEED = (0xCFFA, 2) - # ENEMY_SPECIAL = (0xCFFC, 2) - # ENEMY_MOVE_PP_1 = (0xCFFF, 1) - # ENEMY_MOVE_PP_2 = (0xCFFF, 1) - # ENEMY_MOVE_PP_3 = (0xD000, 1) - # EMENY_MOVE_PP_4 = (0xD001, 1) - # ENEMY_BASE_STATS = (0xD002, 5) - # ENEMY_CATCH_RATE = (0xD007, 1) - # ENEMY_BASE_EXP = (0xD008, 1) - # TYPE_OF_BATTLE = (0xD057, 1) \ No newline at end of file + def __init__(self, fields_to_track=None): + super().__init__(fields_to_track) \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/memory_object.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/memory_object.py new file mode 100644 index 000000000..fa03099bc --- /dev/null +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/memory_object.py @@ -0,0 +1,22 @@ +class MemoryObject(): + + _enum = {} + _lookup = {} + + def __init__(self, fields_to_track): + if fields_to_track is None: + fields_to_track = [e for e in self._enum] + self._fields_to_track = fields_to_track + print(self._fields_to_track) + self._data = {} + + def _load_field_from_memory(self, mem_manager, field_enum): + self.data[field_enum] = mem_manager.read_memory_address(self._lookup[field_enum]) + + def load_from_memory(self, mem_manager): + for field_enum in self._fields_to_track: + self._load_field_from_memory(mem_manager, field_enum) + + def get_value(self, k): + return self._data.get(k) + diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py index 8fb26e61d..0dc7e3a6e 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py @@ -1,143 +1,99 @@ -from ..data.memory_addrs.pokemon import PokemonBaseAddress, PokemonMemoryOffset +from ..data.memory_addrs.pokemon import PokemonBaseAddress, PokemonAddress, POKEMON_ADDRESS_LOOKUP from ..data.constants.pokemon import PokemonId, _POKEMON_NAMES, _POKEMON_POKEDEX_INDEX from .move import Move +from .memory_object import MemoryObject -class Pokemon: +class Pokemon(MemoryObject): - def __init__(self, - pokemon_id, - current_hp, - box_level, - status, - type_1, - type_2, - catch_rate, - move_1, - move_2, - move_3, - move_4, - trainer_id, - experience, - hp_ev, - attack_ev, - defense_ev, - speed_ev, - special_ev, - attack_defense_iv, - speed_special_iv, - pp_move_1, - pp_move_2, - pp_move_3, - pp_move_4, - level, - max_hp=0, - attack=0, - defense=0, - speed=0, - special=0, - in_party=False): - self._pokemon_id = PokemonId(pokemon_id) - self._current_hp = current_hp - self._status = status - self._type_1 = type_1 - self._type_2 = type_2 - self._catch_rate = catch_rate - self._moves = [move_1, move_2, move_3, move_4] - self._trainer_id = trainer_id - self._experience = experience - # EV order: HP, Attack, Defense, Speed, Special - self._evs = [hp_ev, attack_ev, defense_ev, speed_ev, special_ev] - self._attack_defense_iv = attack_defense_iv - self._speed_special_iv = speed_special_iv - self._pp_moves = [pp_move_1, pp_move_2, pp_move_3, pp_move_4] - self._level = level if in_party else box_level - # Stat order same as EV order - self._stats = [max_hp, attack, defense, speed, special] - self._in_party = in_party + _enum = PokemonAddress + _lookup = POKEMON_ADDRESS_LOOKUP + + def __init__(self, fields_to_track): + super().__init__(fields_to_track) @property def name(self): - return Pokemon.get_pokemon_name_from_id(self._pokemon_id) + return Pokemon.get_pokemon_name_from_id(self.get_value(PokemonAddress.ID)) @property def pokedex_num(self): - return Pokemon.get_pokedex_id_from_pokemon_id(self._pokemon_id) + return Pokemon.get_pokedex_id_from_pokemon_id(self.get_value(PokemonAddress.ID)) - @property - def move_1(self): - return self._moves[0] + # @property + # def move_1(self): + # return self._moves[0] - @property - def move_2(self): - return self._moves[1] + # @property + # def move_2(self): + # return self._moves[1] - @property - def move_3(self): - return self._moves[2] + # @property + # def move_3(self): + # return self._moves[2] - @property - def move_4(self): - return self._moves[3] + # @property + # def move_4(self): + # return self._moves[3] - @property - def pp_move_1(self): - return self._pp_moves[0] + # @property + # def pp_move_1(self): + # return self._pp_moves[0] - @property - def pp_move_2(self): - return self._pp_moves[1] + # @property + # def pp_move_2(self): + # return self._pp_moves[1] - @property - def pp_move_3(self): - return self._pp_moves[2] + # @property + # def pp_move_3(self): + # return self._pp_moves[2] - @property - def pp_move_4(self): - return self._pp_moves[3] + # @property + # def pp_move_4(self): + # return self._pp_moves[3] - @property - def hp_ev(self): - return self._evs[0] + # @property + # def hp_ev(self): + # return self._evs[0] - @property - def attack_ev(self): - return self._evs[1] + # @property + # def attack_ev(self): + # return self._evs[1] - @property - def defense_ev(self): - return self._evs[2] + # @property + # def defense_ev(self): + # return self._evs[2] - @property - def speed_ev(self): - return self._evs[3] + # @property + # def speed_ev(self): + # return self._evs[3] - @property - def special_ev(self): - return self._evs[4] + # @property + # def special_ev(self): + # return self._evs[4] - @property - def max_hp(self): - return self._stats[0] + # @property + # def max_hp(self): + # return self._stats[0] - @property - def attack(self): - return self._stats[1] + # @property + # def attack(self): + # return self._stats[1] - @property - def defense(self): - return self._stats[2] + # @property + # def defense(self): + # return self._stats[2] - @property - def speed(self): - return self._stats[3] + # @property + # def speed(self): + # return self._stats[3] - @property - def special(self): - return self._stats[4] + # @property + # def special(self): + # return self._stats[4] - @property - def curr_hp_percent(self): - return self._current_hp / self.max_hp + # @property + # def curr_hp_percent(self): + # return self._current_hp / self.max_hp @staticmethod def get_pokemon_name_from_id(pokemon_id): @@ -146,32 +102,12 @@ def get_pokemon_name_from_id(pokemon_id): @staticmethod def get_pokedex_id_from_pokemon_id(pokemon_id): return _POKEMON_POKEDEX_INDEX.get(PokemonId(pokemon_id)) - @staticmethod - def _load_pokemon_from_address(mem_manager, pokemon_base_address, in_party): - - pokemon_values = [] - - if in_party: - it = list(PokemonMemoryOffset) - else: - # When checking a Pokemon in the box, it does not have the second - # level field or any of its stats saved in memory - it = list(PokemonMemoryOffset)[:-6] - - for offset_enum in [e.value for e in PokemonMemoryOffset]: - offset_addr = offset_enum.add_addr(pokemon_base_address) - memory_value = mem_manager.read_memory_address(offset_addr) - pokemon_values.append(memory_value) - - return Pokemon(*pokemon_values, in_party) - - @classmethod - def load_pokemon_from_party(cls, mem_manager, party_location): - # party_location goes from 1-6 - pokemon_base_address = list(PokemonBaseAddress)[party_location-1].value - return cls._load_pokemon_from_address(mem_manager, pokemon_base_address, in_party=True) + def load_pokemon_from_party(mem_manager, party_id): + pokemon = PartyPokemon(party_id=party_id) + pokemon.load_from_memory(mem_manager) + return pokemon def _generate_move_str(self): s = f"Moves:\n" @@ -193,4 +129,15 @@ def _generate_stats_str(self): def pretty_stringify(self): s = f"{self.name}\n" + self._generate_stats_str() + self._generate_move_str() - return s \ No newline at end of file + return s + +class PartyPokemon(Pokemon): + + def __init__(self, party_id, fields_to_track=None): + super().__init__(fields_to_track) + self._party_id = party_id + + def _load_field_from_memory(self, mem_manager, field_enum): + memory_addr = self._lookup[field_enum] + memory_addr = memory_addr.add_offset([e.value for e in PokemonBaseAddress][self._party_id-1]) + self.data[field_enum] = mem_manager.read_memory_address(self._lookup[field_enum]) \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/base.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/base.py index ff65f606b..0641be678 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/base.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/base.py @@ -1,5 +1,12 @@ from enum import Enum +class MemoryAddressType(Enum): + HEX = 0 + ADDRESS = 1 + BCD = 2 + BITFIELD = 3 + TEXT = 4 + class MemoryAddress(): def __init__(self, address, num_bytes, memory_type): @@ -27,10 +34,27 @@ def add_addr(self, offset): # returns a new tuple with the right values return MemoryAddress(self.address+offset, self.num_bytes, self.memory_type) +class HexMemoryAddress(MemoryAddress): -class MemoryAddressType(Enum): - HEX = 0 - ADDRESS = 1 - BCD = 2 - BITFIELD = 3 - TEXT = 4 \ No newline at end of file + def __init__(self, address, num_bytes): + super().__init__(address, num_bytes, MemoryAddressType.HEX) + +class AddressMemoryAddress(MemoryAddress): + + def __init__(self, address, num_bytes): + super().__init__(address, num_bytes, MemoryAddressType.ADDRESS) + +class BCDMemoryAddress(MemoryAddress): + + def __init__(self, address, num_bytes): + super().__init__(address, num_bytes, MemoryAddressType.BCD) + +class BitfieldMemoryAddress(MemoryAddress): + + def __init__(self, address, num_bytes): + super().__init__(address, num_bytes, MemoryAddressType.BITFIELD) + +class TextMemoryAddress(MemoryAddress): + + def __init__(self, address, num_bytes): + super().__init__(address, num_bytes, MemoryAddressType.TEXT) \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/battle.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/battle.py index 3bb4f7d3b..650b1e6e5 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/battle.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/battle.py @@ -1,48 +1,97 @@ -from .base import MemoryAddressEnum, MemoryAddressType +from enum import Enum, auto +from .base import MemoryAddress, MemoryAddressType -class InternationalBattleAddress(MemoryAddressEnum): - ENEMY_MOVE_ID = (0xCFCC, 1, MemoryAddressType.HEX) - ENEMY_MOVE_EFFECT = (0xCFCD, 1, MemoryAddressType.HEX) - ENEMY_MOVE_POWER = (0xCFCE, 1, MemoryAddressType.HEX) - ENEMY_MOVE_TYPE = (0xCFCF, 1) - ENEMY_MOVE_ACCURACY = (0xCFD0, 1) - ENEMY_MOVE_MAX_PP = (0xCFD1, 1) - PLAYER_MOVE_ID = (0xCFD2, 1) - PLAYER_MOVE_EFFECT = (0xCFD3, 1) - PLAYER_MOVE_POWER = (0xCFD4, 1) - PLAYER_MOVE_TYPE = (0xCFD5, 1) - PLAYER_MOVE_ACCURACY = (0xCFD6, 1) - PLAYER_MOVE_MAX_PP = (0xCFD7, 1) - ENEMY_POKEMON_ID = (0xCFD8, 1) - PLAYER_POKEMON_ID = (0xCFD9, 1) - ENEMY_NAME = (0xCFDA, 10) +class BattleAddress(Enum): + ENEMY_MOVE_ID = auto() + ENEMY_MOVE_EFFECT = auto() + ENEMY_MOVE_POWER = auto() + ENEMY_MOVE_TYPE = auto() + ENEMY_MOVE_ACCURACY = auto() + ENEMY_MOVE_MAX_PP = auto() + PLAYER_MOVE_ID = auto() + PLAYER_MOVE_EFFECT = auto() + PLAYER_MOVE_POWER = auto() + PLAYER_MOVE_TYPE = auto() + PLAYER_MOVE_ACCURACY = auto() + PLAYER_MOVE_MAX_PP = auto() + ENEMY_POKEMON_ID = auto() + PLAYER_POKEMON_ID = auto() + ENEMY_NAME = auto() # This seems to be a repat? - # ENEMY_POKEMON_ID = (0xCFE5, 1) - ENEMY_HP = (0xCFE6, 2) - ENEMY_LEVEL = (0xCFE8, 1) - ENEMY_STATUS = (0xCFE9, 1) - ENEMY_TYPE_1 = (0xCFEA, 1) - ENEMY_TPYE_2 = (0xCFEB, 1) + # ENEMY_POKEMON_ID = 16 + ENEMY_HP = auto() + ENEMY_LEVEL = auto() + ENEMY_STATUS = auto() + ENEMY_TYPE_1 = auto() + ENEMY_TYPE_2 = auto() # ENEMY_CATCH_RATE_UNUSED only checked by move Transform - ENEMY_CATCH_RATE_UNUSED = (0xCFEC, 1) - ENEMY_MOVE_1 = (0xCFED, 1) - ENEMY_MOVE_2 = (0xCFEE, 1) - ENEMY_MOVE_3 = (0xCFEF, 1) - ENEMY_MOVE_4 = (0xCFF0, 1) - ENEMY_ATT_DEF_DVS = (0xCFF1, 1) - ENEMY_SPEED_SPEC_DVS = (0xCFF2, 1) + ENEMY_CATCH_RATE_UNUSED = auto() + ENEMY_MOVE_1 = auto() + ENEMY_MOVE_2 = auto() + ENEMY_MOVE_3 = auto() + ENEMY_MOVE_4 = auto() + ENEMY_ATT_DEF_DVS = auto() + ENEMY_SPEED_SPEC_DVS = auto() # Another repeat? # ENEMY_LEVEL = (0xCFEC) - ENEMY_MAX_HP = (0xCFF4, 2) - ENEMY_ATTACK = (0xCFF6, 2) - ENEMY_DEFENSE = (0xCFF8, 2) - ENEMY_SPEED = (0xCFFA, 2) - ENEMY_SPECIAL = (0xCFFC, 2) - ENEMY_MOVE_PP_1 = (0xCFFF, 1) - ENEMY_MOVE_PP_2 = (0xCFFF, 1) - ENEMY_MOVE_PP_3 = (0xD000, 1) - EMENY_MOVE_PP_4 = (0xD001, 1) - ENEMY_BASE_STATS = (0xD002, 5) - ENEMY_CATCH_RATE = (0xD007, 1) - ENEMY_BASE_EXP = (0xD008, 1) - TYPE_OF_BATTLE = (0xD057, 1) \ No newline at end of file + ENEMY_MAX_HP = auto() + ENEMY_ATTACK = auto() + ENEMY_DEFENSE = auto() + ENEMY_SPEED = auto() + ENEMY_SPECIAL = auto() + ENEMY_MOVE_PP_1 = auto() + ENEMY_MOVE_PP_2 = auto() + ENEMY_MOVE_PP_3 = auto() + EMENY_MOVE_PP_4 = auto() + ENEMY_BASE_STATS = auto() + ENEMY_CATCH_RATE = auto() + ENEMY_BASE_EXP = auto() + TYPE_OF_BATTLE = auto() + +BATTLE_ADDRESS_LOOKUP = { + BattleAddress.ENEMY_MOVE_ID: MemoryAddress(0xCFCC, 1, MemoryAddressType.HEX), + BattleAddress.ENEMY_MOVE_EFFECT: MemoryAddress(0xCFCD, 1, MemoryAddressType.HEX), + BattleAddress.ENEMY_MOVE_POWER: MemoryAddress(0xCFCE, 1, MemoryAddressType.HEX), + BattleAddress.ENEMY_MOVE_TYPE: MemoryAddress(0xCFCF, 1, MemoryAddressType.HEX), + BattleAddress.ENEMY_MOVE_ACCURACY: MemoryAddress(0xCFD0, 1, MemoryAddressType.HEX), + BattleAddress.ENEMY_MOVE_MAX_PP: MemoryAddress(0xCFD1, 1, MemoryAddressType.HEX), + BattleAddress.PLAYER_MOVE_ID: MemoryAddress(0xCFD2, 1, MemoryAddressType.HEX), + BattleAddress.PLAYER_MOVE_EFFECT: MemoryAddress(0xCFD3, 1, MemoryAddressType.HEX), + BattleAddress.PLAYER_MOVE_POWER: MemoryAddress(0xCFD4, 1, MemoryAddressType.HEX), + BattleAddress.PLAYER_MOVE_TYPE: MemoryAddress(0xCFD5, 1, MemoryAddressType.HEX), + BattleAddress.PLAYER_MOVE_ACCURACY: MemoryAddress(0xCFD6, 1, MemoryAddressType.HEX), + BattleAddress.PLAYER_MOVE_MAX_PP: MemoryAddress(0xCFD7, 1, MemoryAddressType.HEX), + BattleAddress.ENEMY_POKEMON_ID: MemoryAddress(0xCFD8, 1, MemoryAddressType.HEX), + BattleAddress.PLAYER_POKEMON_ID: MemoryAddress(0xCFD9, 1, MemoryAddressType.HEX), + BattleAddress.ENEMY_NAME: MemoryAddress(0xCFDA, 10, MemoryAddressType.TEXT), + # This seems to be a repat? + # ENEMY_POKEMON_ID = (0xCFE5, 1, MemoryAddressType.HEX), + BattleAddress.ENEMY_HP: MemoryAddress(0xCFE6, 2, MemoryAddressType.HEX), + BattleAddress.ENEMY_LEVEL: MemoryAddress(0xCFE8, 1, MemoryAddressType.HEX), + BattleAddress.ENEMY_STATUS: MemoryAddress(0xCFE9, 1, MemoryAddressType.HEX), + BattleAddress.ENEMY_TYPE_1: MemoryAddress(0xCFEA, 1, MemoryAddressType.HEX), + BattleAddress.ENEMY_TYPE_2: MemoryAddress(0xCFEB, 1, MemoryAddressType.HEX), + # ENEMY_CATCH_RATE_UNUSED only checked by move Transform + BattleAddress.ENEMY_CATCH_RATE_UNUSED: MemoryAddress(0xCFEC, 1, MemoryAddressType.HEX), + BattleAddress.ENEMY_MOVE_1: MemoryAddress(0xCFED, 1, MemoryAddressType.HEX), + BattleAddress.ENEMY_MOVE_2: MemoryAddress(0xCFEE, 1, MemoryAddressType.HEX), + BattleAddress.ENEMY_MOVE_3: MemoryAddress(0xCFEF, 1, MemoryAddressType.HEX), + BattleAddress.ENEMY_MOVE_4: MemoryAddress(0xCFF0, 1, MemoryAddressType.HEX), + BattleAddress.ENEMY_ATT_DEF_DVS: MemoryAddress(0xCFF1, 1, MemoryAddressType.HEX), + BattleAddress.ENEMY_SPEED_SPEC_DVS: MemoryAddress(0xCFF2, 1, MemoryAddressType.HEX), + # Another repeat? + # ENEMY_LEVEL = MemoryAddress(0xCFEC, 1) + BattleAddress.ENEMY_MAX_HP: MemoryAddress(0xCFF4, 2, MemoryAddressType.HEX), + BattleAddress.ENEMY_ATTACK: MemoryAddress(0xCFF6, 2, MemoryAddressType.HEX), + BattleAddress.ENEMY_DEFENSE: MemoryAddress(0xCFF8, 2, MemoryAddressType.HEX), + BattleAddress.ENEMY_SPEED: MemoryAddress(0xCFFA, 2, MemoryAddressType.HEX), + BattleAddress.ENEMY_SPECIAL: MemoryAddress(0xCFFC, 2, MemoryAddressType.HEX), + BattleAddress.ENEMY_MOVE_PP_1: MemoryAddress(0xCFFF, 1, MemoryAddressType.HEX), + BattleAddress.ENEMY_MOVE_PP_2: MemoryAddress(0xCFFF, 1, MemoryAddressType.HEX), + BattleAddress.ENEMY_MOVE_PP_3: MemoryAddress(0xD000, 1, MemoryAddressType.HEX), + BattleAddress.EMENY_MOVE_PP_4: MemoryAddress(0xD001, 1, MemoryAddressType.HEX), + BattleAddress.ENEMY_BASE_STATS: MemoryAddress(0xD002, 5, MemoryAddressType.HEX), + BattleAddress.ENEMY_CATCH_RATE: MemoryAddress(0xD007, 1, MemoryAddressType.HEX), + BattleAddress.ENEMY_BASE_EXP: MemoryAddress(0xD008, 1, MemoryAddressType.HEX), + BattleAddress.TYPE_OF_BATTLE: MemoryAddress(0xD057, 1, MemoryAddressType.HEX), +} \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/pokemon.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/pokemon.py index 4bdc2aaf7..cc4bb1609 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/pokemon.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/pokemon.py @@ -1,6 +1,6 @@ # Pokemon locations in memory -from enum import Enum -from .base import MemoryAddress, MemoryAddressType +from enum import Enum, auto +from .base import HexMemoryAddress class PokemonBaseAddress(Enum): POKEMON_1 = 0xD16B @@ -12,34 +12,67 @@ class PokemonBaseAddress(Enum): # Offsets for Pokemon data access # Structure is (offset, num bytes) -class PokemonMemoryOffset(Enum): - ID = MemoryAddress(0x0, 1, MemoryAddressType.HEX) - CURRENT_HP = MemoryAddress(0x1, 2, MemoryAddressType.HEX) - BOX_LEVEL = MemoryAddress(0x3, 1, MemoryAddressType.HEX) - STATUS = MemoryAddress(0x4, 1, MemoryAddressType.HEX) - TYPE_1 = MemoryAddress(0x5, 1, MemoryAddressType.HEX) - TYPE_2 = MemoryAddress(0x6, 1, MemoryAddressType.HEX) - CATCH_RATE = MemoryAddress(0x7, 1, MemoryAddressType.HEX) - MOVE_1 = MemoryAddress(0x8, 1, MemoryAddressType.HEX) - MOVE_2 = MemoryAddress(0x9, 1, MemoryAddressType.HEX) - MOVE_3 = MemoryAddress(0xA, 1, MemoryAddressType.HEX) - MOVE_4 = MemoryAddress(0xB, 1, MemoryAddressType.HEX) - TRAINER_ID = MemoryAddress(0xC, 2, MemoryAddressType.HEX) - EXPERIENCE = MemoryAddress(0xE, 3, MemoryAddressType.HEX) - HP_EV = MemoryAddress(0x11, 2, MemoryAddressType.HEX) - ATTACK_EV = MemoryAddress(0x13, 2, MemoryAddressType.HEX) - DEFENSE_EV = MemoryAddress(0x15, 2, MemoryAddressType.HEX) - SPEED_EV = MemoryAddress(0x17, 2, MemoryAddressType.HEX) - SPECIAL_EV = MemoryAddress(0x19, 2, MemoryAddressType.HEX) - ATTACK_DEFENSE_IV = MemoryAddress(0x1B, 1, MemoryAddressType.HEX) - SPEED_SPECIAL_IV = MemoryAddress(0x1C, 1, MemoryAddressType.HEX) - PP_MOVE_1 = MemoryAddress(0x1D, 1, MemoryAddressType.HEX) - PP_MOVE_2 = MemoryAddress(0x1E, 1, MemoryAddressType.HEX) - PP_MOVE_3 = MemoryAddress(0x1F, 1, MemoryAddressType.HEX) - PP_MOVE_4 = MemoryAddress(0x20, 1, MemoryAddressType.HEX) - LEVEL = MemoryAddress(0x21, 1, MemoryAddressType.HEX) - MAX_HP = MemoryAddress(0x22, 2, MemoryAddressType.HEX) - ATTACK = MemoryAddress(0x24, 2, MemoryAddressType.HEX) - DEFENSE = MemoryAddress(0x26, 2, MemoryAddressType.HEX) - SPEED = MemoryAddress(0x28, 2, MemoryAddressType.HEX) - SPECIAL = MemoryAddress(0x2A, 2, MemoryAddressType.HEX) \ No newline at end of file +class PokemonAddress(Enum): + ID = auto() + CURRENT_HP = auto() + BOX_LEVEL = auto() + STATUS = auto() + TYPE_1 = auto() + TYPE_2 = auto() + CATCH_RATE = auto() + MOVE_1 = auto() + MOVE_2 = auto() + MOVE_3 = auto() + MOVE_4 = auto() + TRAINER_ID = auto() + EXPERIENCE = auto() + HP_EV = auto() + ATTACK_EV = auto() + DEFENSE_EV = auto() + SPEED_EV = auto() + SPECIAL_EV = auto() + ATTACK_DEFENSE_IV = auto() + SPEED_SPECIAL_IV = auto() + PP_MOVE_1 = auto() + PP_MOVE_2 = auto() + PP_MOVE_3 = auto() + PP_MOVE_4 = auto() + LEVEL = auto() + MAX_HP = auto() + ATTACK = auto() + DEFENSE = auto() + SPEED = auto() + SPECIAL = auto() + +POKEMON_ADDRESS_LOOKUP = { + PokemonAddress.ID: HexMemoryAddress(0x0, 1), + PokemonAddress.CURRENT_HP: HexMemoryAddress(0x1, 2), + PokemonAddress.BOX_LEVEL: HexMemoryAddress(0x3, 1), + PokemonAddress.STATUS: HexMemoryAddress(0x4, 1), + PokemonAddress.TYPE_1: HexMemoryAddress(0x5, 1), + PokemonAddress.TYPE_2: HexMemoryAddress(0x6, 1), + PokemonAddress.CATCH_RATE: HexMemoryAddress(0x7, 1), + PokemonAddress.MOVE_1: HexMemoryAddress(0x8, 1), + PokemonAddress.MOVE_2: HexMemoryAddress(0x9, 1), + PokemonAddress.MOVE_3: HexMemoryAddress(0xA, 1), + PokemonAddress.MOVE_4: HexMemoryAddress(0xB, 1), + PokemonAddress.TRAINER_ID: HexMemoryAddress(0xC, 2), + PokemonAddress.EXPERIENCE: HexMemoryAddress(0xE, 3), + PokemonAddress.HP_EV: HexMemoryAddress(0x11, 2), + PokemonAddress.ATTACK_EV: HexMemoryAddress(0x13, 2), + PokemonAddress.DEFENSE_EV: HexMemoryAddress(0x15, 2), + PokemonAddress.SPEED_EV: HexMemoryAddress(0x17, 2), + PokemonAddress.SPECIAL_EV: HexMemoryAddress(0x19, 2), + PokemonAddress.ATTACK_DEFENSE_IV: HexMemoryAddress(0x1B, 1), + PokemonAddress.SPEED_SPECIAL_IV: HexMemoryAddress(0x1C, 1), + PokemonAddress.PP_MOVE_1: HexMemoryAddress(0x1D, 1), + PokemonAddress.PP_MOVE_2: HexMemoryAddress(0x1E, 1), + PokemonAddress.PP_MOVE_3: HexMemoryAddress(0x1F, 1), + PokemonAddress.PP_MOVE_4: HexMemoryAddress(0x20, 1), + PokemonAddress.LEVEL: HexMemoryAddress(0x21, 1), + PokemonAddress.MAX_HP: HexMemoryAddress(0x22, 2), + PokemonAddress.ATTACK: HexMemoryAddress(0x24, 2), + PokemonAddress.DEFENSE: HexMemoryAddress(0x26, 2), + PokemonAddress.SPEED: HexMemoryAddress(0x28, 2), + PokemonAddress.SPECIAL: HexMemoryAddress(0x2A, 2), +} \ No newline at end of file From 1e16becbc24144eff16f0ee909e827d471bd131a Mon Sep 17 00:00:00 2001 From: SnarkAttack Date: Tue, 5 Dec 2023 16:45:48 -0500 Subject: [PATCH 67/74] Rename add_address to add_offset --- .../game_wrapper_pokemon_gen1/data/memory_addrs/base.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/base.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/base.py index 0641be678..cf6a0a0fb 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/base.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/base.py @@ -29,9 +29,7 @@ def memory_type(self): def __str__(self): return f"Memory address: {self._address}: Length: {self._num_bytes}, memory_addr_type: {self._memory_type}" - def add_addr(self, offset): - # Super hacky way to 'add' an offset to an enum, which just - # returns a new tuple with the right values + def add_offset(self, offset): return MemoryAddress(self.address+offset, self.num_bytes, self.memory_type) class HexMemoryAddress(MemoryAddress): From 9623437697bdb549b5c62ce8e4734ba7af3e2ef1 Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Tue, 5 Dec 2023 17:24:26 -0500 Subject: [PATCH 68/74] Remove print statement that was acidentally committed --- pyboy/plugins/game_wrapper_pokemon_gen1/core/memory_object.py | 1 - pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/memory_object.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/memory_object.py index fa03099bc..0657d2b57 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/memory_object.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/memory_object.py @@ -7,7 +7,6 @@ def __init__(self, fields_to_track): if fields_to_track is None: fields_to_track = [e for e in self._enum] self._fields_to_track = fields_to_track - print(self._fields_to_track) self._data = {} def _load_field_from_memory(self, mem_manager, field_enum): diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py index 0dc7e3a6e..01c237700 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py @@ -140,4 +140,4 @@ def __init__(self, party_id, fields_to_track=None): def _load_field_from_memory(self, mem_manager, field_enum): memory_addr = self._lookup[field_enum] memory_addr = memory_addr.add_offset([e.value for e in PokemonBaseAddress][self._party_id-1]) - self.data[field_enum] = mem_manager.read_memory_address(self._lookup[field_enum]) \ No newline at end of file + self._data[field_enum] = mem_manager.read_memory_address(self._lookup[field_enum]) \ No newline at end of file From 5cbb27ead321f161b0060c8f311927976937f003 Mon Sep 17 00:00:00 2001 From: Patrick McQuay Date: Tue, 5 Dec 2023 18:01:39 -0500 Subject: [PATCH 69/74] Update Player class to use new memory reading approach --- .../game_wrapper_pokemon_gen1/core/player.py | 52 +++---- .../game_wrapper_pokemon_gen1/core/pokemon.py | 127 +++++++++--------- .../data/memory_addrs/player.py | 20 ++- 3 files changed, 99 insertions(+), 100 deletions(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py index fd28f627d..584478db4 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/player.py @@ -1,19 +1,15 @@ -from ..data.memory_addrs.player import PlayerAddress +from ..data.memory_addrs.player import PlayerAddress, PLAYER_ADDRESS_LOOKUP from ..data.constants.pokemon import PokemonId from ..data.constants.misc import Badge +from .memory_object import MemoryObject -class Player: +class Player(MemoryObject): - def __init__(self, - name, - pokemon_in_party, - badges, - money): - - self._name = name - self._pokemon_in_party = pokemon_in_party - self._badges = badges - self._money = money + _enum = PlayerAddress + _lookup = PLAYER_ADDRESS_LOOKUP + + def __init__(self, fields_to_track): + super().__init__(fields_to_track) ''' Getters and setters @@ -57,29 +53,19 @@ def remove_badge(self, badge : Badge): self._badges[badge.value] = 0 @staticmethod - def load_player(mem_manager): - - name = mem_manager.read_memory_address(PlayerAddress.NAME) - - num_pokemon_in_party = mem_manager.read_memory_address(PlayerAddress.NUM_POKEMON_IN_PARTY) - - pokemon_in_party = [PokemonId(mem_manager.read_memory_address(PlayerAddress.NUM_POKEMON_IN_PARTY.add_addr(i+1))) - for i in range(num_pokemon_in_party)] - - badges = mem_manager.read_memory_address(PlayerAddress.BADGES) - - money = mem_manager.read_memory_address(PlayerAddress.MONEY) - - return Player(name, pokemon_in_party, badges, money) + def load_player(mem_manager, fields_to_track=None): + player = Player(mem_manager, fields_to_track) + player.load_from_memory(mem_manager) + return player - def save_player(self, mem_manager): + # def save_player(self, mem_manager): - mem_manager.write_memory_address(self._name, PlayerAddress.NAME) - mem_manager.write_memory_address(self.num_pokemon_in_party, PlayerAddress.NUM_POKEMON_IN_PARTY) - # TODO: Figure out the loading and unloading of Pokemon in party, as that should be in tandem with - # Pokemon class so that data does not get out of sync - mem_manager.write_memory_address(self._badges, PlayerAddress.BADGES) - mem_manager.write_memory_address(self._money, PlayerAddress.MONEY) + # mem_manager.write_memory_address(self._name, PlayerAddress.NAME) + # mem_manager.write_memory_address(self.num_pokemon_in_party, PlayerAddress.NUM_POKEMON_IN_PARTY) + # # TODO: Figure out the loading and unloading of Pokemon in party, as that should be in tandem with + # # Pokemon class so that data does not get out of sync + # mem_manager.write_memory_address(self._badges, PlayerAddress.BADGES) + # mem_manager.write_memory_address(self._money, PlayerAddress.MONEY) \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py index 01c237700..a1d2ea60d 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py @@ -18,82 +18,86 @@ def name(self): @property def pokedex_num(self): return Pokemon.get_pokedex_id_from_pokemon_id(self.get_value(PokemonAddress.ID)) + + @property + def current_hp(self): + return self.get_value(PokemonAddress.CURRENT_HP) - # @property - # def move_1(self): - # return self._moves[0] + @property + def move_1(self): + return self.get_value(PokemonAddress.MOVE_1) - # @property - # def move_2(self): - # return self._moves[1] + @property + def move_2(self): + return self.get_value(PokemonAddress.MOVE_2) - # @property - # def move_3(self): - # return self._moves[2] + @property + def move_3(self): + return self.get_value(PokemonAddress.MOVE_3) - # @property - # def move_4(self): - # return self._moves[3] + @property + def move_4(self): + return self.get_value(PokemonAddress.MOVE_4) - # @property - # def pp_move_1(self): - # return self._pp_moves[0] + @property + def pp_move_1(self): + return self.get_value(PokemonAddress.PP_MOVE_1) - # @property - # def pp_move_2(self): - # return self._pp_moves[1] + @property + def pp_move_2(self): + return self.get_value(PokemonAddress.PP_MOVE_2) - # @property - # def pp_move_3(self): - # return self._pp_moves[2] + @property + def pp_move_3(self): + return self.get_value(PokemonAddress.PP_MOVE_3) - # @property - # def pp_move_4(self): - # return self._pp_moves[3] + @property + def pp_move_4(self): + return self.get_value(PokemonAddress.PP_MOVE_4) - # @property - # def hp_ev(self): - # return self._evs[0] + @property + def hp_ev(self): + return self.get_value(PokemonAddress.HP_EV) - # @property - # def attack_ev(self): - # return self._evs[1] + @property + def attack_ev(self): + return self.get_value(PokemonAddress.ATTACK_EV) - # @property - # def defense_ev(self): - # return self._evs[2] + @property + def defense_ev(self): + return self.get_value(PokemonAddress.DEFENSE_EV) - # @property - # def speed_ev(self): - # return self._evs[3] + @property + def speed_ev(self): + return self.get_value(PokemonAddress.SPEED_EV) - # @property - # def special_ev(self): - # return self._evs[4] + @property + def special_ev(self): + return self.get_value(PokemonAddress.SPECIAL_EV) - # @property - # def max_hp(self): - # return self._stats[0] + @property + def max_hp(self): + return self.get_value(PokemonAddress.MAX_HP) - # @property - # def attack(self): - # return self._stats[1] + @property + def attack(self): + return self.get_value(PokemonAddress.ATTACK) - # @property - # def defense(self): - # return self._stats[2] + @property + def defense(self): + return self.get_value(PokemonAddress.DEFENSE) - # @property - # def speed(self): - # return self._stats[3] + @property + def speed(self): + return self.get_value(PokemonAddress.SPEED) - # @property - # def special(self): - # return self._stats[4] + @property + def special(self): + return self.get_value(PokemonAddress.SPECIAL) - # @property - # def curr_hp_percent(self): - # return self._current_hp / self.max_hp + @property + def curr_hp_percent(self): + return self.current_hp / self.max_hp @staticmethod def get_pokemon_name_from_id(pokemon_id): @@ -111,9 +115,10 @@ def load_pokemon_from_party(mem_manager, party_id): def _generate_move_str(self): s = f"Moves:\n" - - for i, move_id in enumerate(self._moves): - s += f"\t{Move.get_name_from_id(move_id)} ({self._pp_moves[i]}/)\n" + s += f"\t{Move.get_name_from_id(self.move_1)} ({self.pp_move_1}/)\n" + s += f"\t{Move.get_name_from_id(self.move_2)} ({self.pp_move_2}/)\n" + s += f"\t{Move.get_name_from_id(self.move_3)} ({self.pp_move_3}/)\n" + s += f"\t{Move.get_name_from_id(self.move_4)} ({self.pp_move_4}/)\n" return s @@ -140,4 +145,4 @@ def __init__(self, party_id, fields_to_track=None): def _load_field_from_memory(self, mem_manager, field_enum): memory_addr = self._lookup[field_enum] memory_addr = memory_addr.add_offset([e.value for e in PokemonBaseAddress][self._party_id-1]) - self._data[field_enum] = mem_manager.read_memory_address(self._lookup[field_enum]) \ No newline at end of file + self._data[field_enum] = mem_manager.read_memory_address(memory_addr) \ No newline at end of file diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/player.py b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/player.py index 5ff245f3c..86b490e09 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/player.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/data/memory_addrs/player.py @@ -1,8 +1,16 @@ -from enum import Enum -from .base import MemoryAddress, MemoryAddressType +from enum import Enum, auto +from .base import HexMemoryAddress, BCDMemoryAddress, TextMemoryAddress class PlayerAddress(Enum): - NAME = MemoryAddress(0xD158, 10, MemoryAddressType.TEXT) - NUM_POKEMON_IN_PARTY = MemoryAddress(0xD163, 1, MemoryAddressType.HEX) - BADGES = MemoryAddress(0xD356, 1, MemoryAddressType.HEX) - MONEY = MemoryAddress(0xD347, 3, MemoryAddressType.BCD) \ No newline at end of file + NAME = auto() + NUM_POKEMON_IN_PARTY = auto() + BADGES = auto() + MONEY = auto() + +PLAYER_ADDRESS_LOOKUP = { + PlayerAddress.NAME: TextMemoryAddress(0xD158, 10), + PlayerAddress.NUM_POKEMON_IN_PARTY: HexMemoryAddress(0xD163, 1), + PlayerAddress.BADGES: HexMemoryAddress(0xD356, 1), + PlayerAddress.MONEY: BCDMemoryAddress(0xD347, 3) + +} \ No newline at end of file From 08977716ce062d4978485b7c7ad16d077bdbff65 Mon Sep 17 00:00:00 2001 From: SnarkAttack Date: Wed, 6 Dec 2023 16:28:31 -0500 Subject: [PATCH 70/74] Add map_id to player location result and add access to screen in wrapper so we have to pass less things outside of PyBoy --- .../game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py index b26a1ad63..64a920821 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py @@ -120,12 +120,19 @@ def get_player(self): def get_player_location(self): player_sprite_y = self.mem_manager.read_hex_from_memory(0xD361, 1) player_sprite_x = self.mem_manager.read_hex_from_memory(0xD362, 1) + player_sprite_map_id = self.mem_manager.read_hex_from_memory(0xD35E, 1) return (player_sprite_x, player_sprite_y) def get_game_state(self): return GameState.load_game_state(self.mem_manager) + def get_screen(self): + return self.pyboy.botsupport_manager().screen() + + def get_screen_array(self): + return self.get_screen().screen_ndarray() + ''' WARNING From 437a8ea6244994e8f7a373a9876ebeb86532d67e Mon Sep 17 00:00:00 2001 From: SnarkAttack Date: Thu, 7 Dec 2023 09:10:49 -0500 Subject: [PATCH 71/74] Add function to return all Pokemon in party --- .../game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py index 64a920821..c203f49bd 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py @@ -110,6 +110,11 @@ def __repr__(self): def get_pokemon_from_party(self, party_index): return Pokemon.load_pokemon_from_party(self.mem_manager, party_index) + + def get_all_pokemon_from_party(self): + num_pokemon = self.mem_manager.read_hex_from_memory(0xD163, 1) + pokemon_team = [self.get_pokemon_from_party(i+1) for i in range(num_pokemon)] + return pokemon_team def get_pokedex(self): return Pokedex.load_pokedex(self.mem_manager) From 35101334ac5fb5e283db50b7c34de60379951cc8 Mon Sep 17 00:00:00 2001 From: SnarkAttack Date: Thu, 7 Dec 2023 11:47:28 -0500 Subject: [PATCH 72/74] Add experience property to Pokemon --- pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py index a1d2ea60d..f299fe227 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/pokemon.py @@ -39,6 +39,10 @@ def move_3(self): def move_4(self): return self.get_value(PokemonAddress.MOVE_4) + @property + def experience(self): + return self.get_value(PokemonAddress.EXPERIENCE) + @property def pp_move_1(self): return self.get_value(PokemonAddress.PP_MOVE_1) From 2ac86f398664342f9675e1910f04b472917b7d05 Mon Sep 17 00:00:00 2001 From: SnarkAttack Date: Fri, 15 Dec 2023 15:49:29 -0500 Subject: [PATCH 73/74] Add function to read ROM, not exposed out of class because we don't want this being commonly used --- .../core/mem_manager.py | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py b/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py index 09a2ef8cf..e99fed0ad 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/core/mem_manager.py @@ -47,6 +47,8 @@ def get_character_index(character): # number return index + 197 return index + ASCII_DELTA + + def get_ def _read_byte(self, addr): return self.pyboy.get_memory_value(addr) @@ -176,4 +178,28 @@ def write_memory_address(self, mem_addr): raise ValueError(f"{mem_addr.memory_type} is not a valid memory type") return mem_func(mem_addr.address, mem_addr.num_bytes) + + def _load_rombank(self, rombank_selected): + self.pyboy.set_memory_value(0x2000, rombank_selected) + + def read_from_rom(self, address, num_bytes=1): + rombank = int(address / 0x4000) + address_in_rom = address % 0x4000 + + # PyBoy treats the switchable ROM bank as being at address + # 0x4000 to 0x8000 (0x0000 to 0x4000 is always ROM bank 0), + # append 04x4000 + + address_in_rom += 0x4000 + + # Switch in correct ROM bank + self._load_rombank(rombank) + + rom_values = [] + + for i in range(num_bytes): + rom_values.append(self.pyboy.get_memory_value(address_in_rom+i)) + + return rom_values + \ No newline at end of file From 7e4f4a81324c20d2b4b62b8f822e7c37d4fd2c87 Mon Sep 17 00:00:00 2001 From: SnarkAttack Date: Fri, 15 Dec 2023 16:13:55 -0500 Subject: [PATCH 74/74] Give access to ROM reading memory --- .../game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py index c203f49bd..e5e07c322 100644 --- a/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py +++ b/pyboy/plugins/game_wrapper_pokemon_gen1/game_wrapper_pokemon_gen1.py @@ -161,4 +161,7 @@ def read_memory(self, address, num_bytes, read_type): elif read_type == 'text': return self.mem_manager.read_text_from_memory(address, num_bytes) else: - raise ValueError(f"{read_type} is not a valid read type") \ No newline at end of file + raise ValueError(f"{read_type} is not a valid read type") + + def read_rom_memory(self, address, num_bytes): + return self.mem_manager.read_from_rom(address, num_bytes) \ No newline at end of file