PokéBot Gen3 (libmgba) is a bot, written in Python that automatically shiny hunts in Pokémon Ruby, Sapphire, Emerald, FireRed and LeafGreen.
Initially created to complete a Prof. Oak and Living ✨Shiny✨ Dex Challenge in Pokémon Emerald, a 🔴24/7 livestream of the challenge can be found ongoing here.
pokebot-gen3.mp4
Main Interface | Load Save State | Debugger |
---|---|---|
Shiny Notifications | Phase Stats | Milestones |
- This is still in development, as such, functionality is subject to change without warning - always make sure you back up your
profiles/<profile name>/
folder before updating your bot! - Reach out in Discord #bot-support-libmgba❔ if you have any issues
The bot is frame perfect and can cheat by reading data from any point in memory. By default it will attempt to perform most actions as if a human were playing to make gameplay as representative as possible, some examples:
- Starter Pokémon are generated just 1 frame after confirming the starter selection, the bot will wait until the battle begins, and the starter Pokémon sprite is visible before resetting
- It's possible to peek inside un-hatched eggs to view stats and shininess as soon as they're received from the daycare, the bot will wait until the eggs are fully hatched before checking and logging
- These are intentional design decisions, bot cheats can be used to bypass them (in most cases)
- Running mGBA at unbound speeds, will cause very fast and bright flashing!
- Any unbounded video examples on this page will be hidden by default, and marked with ⚠ photosensitivity warning
- Windows (64-bit)
- Linux (64-bit)
- Note: only tested and confirmed working on Ubuntu 23.04, 23.10 and Debian 12
To download the latest bot from GitHub, go to the top of the page > click the green Code button > Download ZIP.
Alternatively, if you'd like to be able to easily pull the latest updates without re-downloading the entire ZIP:
- Install GitHub Desktop (you don't need an account)
- Click Clone a repository from the Internet...
- Use repository URL
https://github.com/40Cakes/pokebot-gen3.git
and choose a save location on your PC - Click Clone
- Any time there's a new update, you can pull the latest changes by clicking Fetch origin, then Pull origin
- Python 3.12 (64-bit)
- Linux only: Install the following packages with
apt
or appropriate package manager:sudo apt install python3-tk libmgba0.10 portaudio19-dev
- Note: running the bot will automatically install required Python packages and download + extract libmgba - if you're using Python for any other projects, consider using a venv to isolate these packages from your base environment
- Windows Terminal - recommended for full 🌈colour🌈 and ✨emoji support✨ in the console output
- Notepad++ - recommended for syntax highlighting while editing
.yml
config files
- Place some official Pokémon .gba ROMs into the
roms/
folder - Double click
pokebot.py
or runpython pokebot.py
in a terminal and follow the on-screen steps to create and/or select a profile
The bot ships with the default mGBA input mapping, see profiles/keys.yml
to view the default mapping, or customise them to your preference.
The bot will pause once a shiny is encountered. You must ensure you are able to escape battle 100% of the time, otherwise the bot will get stuck. Auto-catching and other features will be added in due time.
If you have a save from mGBA that you'd like to import and use with the bot, then you will need to import the save state.
- In mGBA, run a game and load into the save file
- File > Save State File... > Save
- Double click
pokebot.py
or runpython pokebot.py
in a terminal > type a profile name > click Load Existing Save - Open the save state file you just saved
- A new bot profile will be created in the
profiles/
folder and set up all required files
Variations of games, languages and revisions may have different memory offsets, there will be a table of supported/tested variations under each bot mode listed below.
- ✅ Supported (tested)
- 🟨 Supported (not tested)
- ❌ Not supported
ROM hacks will likely not work, and are ❌ not supported or planned to be supported!
The ROMs in the roms/
folder are checked and verified against a list of all known official gen3 game hashes. If you really want to test a ROM hack with the bot, you must add the SHA1 hash of the ROM to modules/Roms.py
.
The SHA1 hash of a ROM can be calculated with any of the following methods:
- ROM Hasher
- Windows Powershell:
Get-FileHash 'rom_name.gba' -Algorithm SHA1
- Linux:
sha1sum 'rom_name.gba'
Please do not seek support or complain if you find that your ROM hack does not work with the bot.
- The bot mode can be changed at any time while the bot is running by using the menu on the UI
Manual
mode is the default mode- Press
Tab
to toggle betweenManual
mode and a previously selected mode
Manual mode simply disables all bot inputs, allowing you to track encounters and stats on your own shiny hunts as you play the game normally.
Spin clockwise on a single tile, useful for Safari Zone and repel tricking as it doesn't count steps
Start the mode while in the overworld, in any patch of grass/water/cave.
🎥 Click here to show a video example
spin.mp4
✅🟨❌ Click here for support information
🟥 Ruby | 🔷 Sapphire | 🟢 Emerald | 🔥 FireRed | 🌿 LeafGreen | |
---|---|---|---|---|---|
English | ✅ | ✅ | ✅ | ✅ | ✅ |
Japanese | 🟨 | 🟨 | 🟨 | 🟨 | 🟨 |
German | 🟨 | 🟨 | 🟨 | 🟨 | 🟨 |
Spanish | 🟨 | 🟨 | 🟨 | 🟨 | 🟨 |
French | 🟨 | 🟨 | 🟨 | 🟨 | 🟨 |
Italian | 🟨 | 🟨 | 🟨 | 🟨 | 🟨 |
Soft reset for starter Pokémon.
🎥 Click here to show a video example
hoenn_starters.mp4
- For modes that use soft resets such as starters, the bot will track RNG to ensure a unique frame is hit after every reset, this is to prevent repeatedly generating an identical Pokémon, this will cause soft resets to take progressively longer over time
- If resets begin to take too long, it is recommended to start a new save file with a different TID to reset this delay or check out
profiles/cheats.yml
- Note: Even though you set the trainer to face the desired PokéBall, it is still important to set the correct
starter
in the config! This option is used by the bot to track frames to ensure a unique starter is generated every time - Note: For the time being, Johto starters will automatically enable the
starters
option inprofiles/cheats.yml
, the shininess of the starter is checked via memhacks as start menu navigation is WIP (in future, shininess will be checked via the party summary menu)
- Select the
starter
inprofiles/general.yml
-Bulbasaur
,Charmander
orSquirtle
- Face the desired PokéBall in Oak's lab, save the game (in-game, not a save state)
- Start the bot
- Select the
starter
inprofiles/general.yml
-Chikorita
,Cyndaquil
orTotodile
- Face the desired PokéBall in Birch's lab, save the game (in-game, not a save state)
- Start the bot
- Select the
starter
inprofiles/general.yml
-Treecko
,Torchic
orMudkip
- Face the starters bag, and save the game (in-game, not a save state)
- Start the bot
✅🟨❌ Click here for support information
🟥 Ruby | 🔷 Sapphire | 🟢 Emerald | 🔥 FireRed | 🌿 LeafGreen | |
---|---|---|---|---|---|
English | ✅ | ✅ | ✅ | ✅ | ✅ |
Japanese | - | - | - | - | - |
German | - | - | - | - | - |
Spanish | - | - | - | - | - |
French | - | - | - | - | - |
Italian | - | - | - | - | - |
Start the mode while facing the water, with any fishing rod registered.
🎥 Click here to show a video example
fishing.mp4
✅🟨❌ Click here for support information
🟥 Ruby | 🔷 Sapphire | 🟢 Emerald | 🔥 FireRed | 🌿 LeafGreen | |
---|---|---|---|---|---|
English | ✅ | ✅ | ✅ | ✅ | ✅ |
Japanese | - | - | - | - | - |
German | - | - | - | - | - |
Spanish | - | - | - | - | - |
French | - | - | - | - | - |
Italian | - | - | - | - | - |
Bunny hop on the spot with the Acro Bike, useful for Safari Zone and repel tricking as it doesn't count steps.
Start the mode while in the overworld, in any patch of grass/cave, with the Acro Bike registered.
- Note:
Bunny Hop
is ~10% slower encounters/h on average thanspin
mode
🎥 Click here to show a video example
bunny_hop.mp4
✅🟨❌ Click here for support information
🟥 Ruby | 🔷 Sapphire | 🟢 Emerald | |
---|---|---|---|
English | ✅ | ✅ | ✅ |
Japanese | - | - | - |
German | - | - | - |
Spanish | - | - | - |
French | - | - | - |
Italian | - | - | - |
Configuration files are loaded and validated against a schema, once at bot launch. Any changes made while the bot is running will not take effect until the bot is stopped and restarted.
A lot of the config in .yml
files is placeholder for future/planned features.
The bot stores all profile information, such as save games, screenshots, statistics, etc. in the profile profiles/<profile name>/
) folder, which is automatically created once you create a new profile in the GUI.
Running multiple instances of the bot is as easy as starting the bot multiple times and loading a different profile each time. You should not run multiple instances of the bot with the same profile simultaneously!
Statistics are saved into a subfolder of your profile profiles/<profile name>/stats/
.
The bot will first attempt to load individual config files from your profile folder (profiles/<profile name>/
), if that folder does not exist or any of the configuration files are missing, it will load the default config file in the profiles/
folder. This allows you to selectively override specific config files on a per-profile basis.
Example:
├── /profiles
│
├── /emerald-profile
│ current_save.sav
│ current_state.ss1
│ discord.yml <-- config loaded for 'emerald-profile'
│ general.yml <-- config loaded for 'emerald-profile'
│
├── /firered-profile
│ current_save.sav
│ current_state.ss1
│ general.yml <-- config loaded for 'firered-profile'
│
│ catch_block.yml <-- config loaded for all profiles
│ cheats.yml <-- config loaded for all profiles
│ customcatchfilters.py <-- config loaded for all profiles
│ customhooks.py <-- config loaded for all profiles
│ discord.yml <-- config loaded for all profiles except 'emerald-profile'
│ general.yml <-- config loaded for all profiles except 'emerald-profile' and 'firered-profile'
│ logging.yml <-- config loaded for all profiles
│ obs.yml <-- config loaded for all profiles
This file controls keyboard to GBA button mappings.
- A button:
X
- B button:
Z
- D-Pad: Arrow keys (
Up
,Down
,Left
,Right
) - Start button:
Enter
- Select button:
Backspace
- Toggle manual bot mode on/off:
Tab
- Toggle video output on/off:
V
- Toggle audio output on/off:
B
- Zoom window scaling in/out:
+
,-
- Create save state:
Ctrl + S
- Load save state menu:
Ctrl + L
- Reset emulator/reboot game:
Ctrl + R
- Exit the bot and emulator:
Ctrl + Q
- Emulator speed:
- 1x speed:
1
- 2x speed:
2
- 3x speed:
3
- 4x speed:
4
- Unbound:
0
- ⚠ Photosensitivity warning: this will run the emulator as fast as possible!
- 1x speed:
Click to expand
starter
- choose which starter Pokémon to hunt for, used when bot mode is set to starters
(see 💼 starters)
Click to expand
log_encounters
- log all encounters to .csv (stats/encounters/
folder), each phase is logged to a separate file
The following console
options will control how much data is displayed in the Python terminal/console, valid options are verbose
, basic
or disable
encounter_data
encounter_ivs
encounter_moves
statistics
The bot can dump individual Pokémon files (.pk3 format) to be managed/transferred in the PKHeX save editor.
The Pokémon are dumped to the pokemon/
folder in your profile, in the following format:
273 ★ - SEEDOT - Modest [180] - C88CF14B19C6.pk3
(<nat_dex_num> <shiny ★> - <mon_name> - <nature> [<IV sum>] - <pid>.pk3
)
save_pk3
:
all
- dump all encountersshiny
- dump shiny encounterscustom
- dump custom catch filter encounters
Feel free to share any rare/interesting .pk3 files in #pkhexchange💱!
While auto-catch is currently still a work in progress, the following option automatically import encountered Pokémon into your PC storage.
Imported Pokémon will be placed into the first available PC slot, in a regular PokéBall.
If space is available in the PC, and the Pokémon was successfully imported, the bot will run from the encounter and continue to hunt.
import_pk3
- enable automatic .pk3 import to PC storage
Click to expand
For privacy reasons, rich presence and webhooks are disabled by default.
rich_presence
- Rich presence will display information on your Discord profile such as game, route, total encounters, total shinies and encounter rate.
global_webhook_url
- global Discord webhook URL, default webhook for all Discord webhooks unless specified otherwise
- ⚠ Warning: this webhook is considered sensitive! If you leak your webhook, anyone will be able to post in your channel
- Edit Channel > Integrations > Webhooks > New Webhook > Copy Webhook URL to generate a new webhook
iv_format
- changes IV formatting displayed in messages, set to basic
or formatted
-
basic
:HP: 31 | ATK: 31 | DEF: 31 | SPA: 31 | SPD: 31 | SPE: 31
-
formatted
:╔═══╤═══╤═══╤═══╤═══╤═══╗ ║HP │ATK│DEF│SPA│SPD│SPE║ ╠═══╪═══╪═══╪═══╪═══╪═══╣ ║31 │31 │31 │31 │31 │31 ║ ╚═══╧═══╧═══╧═══╧═══╧═══╝
bot_id
- set to any string you want, this string is added to the footer of all Discord messages, it can be useful to identify bots if multiple are set to post in the same channel
enable
- toggle the webhook on/off
webhook_url
- set to post specific message types to different channels, defaults to global_webhook_url
if not set
- Commented out in config file by default, remove the leading
#
to uncomment
Each webhook type also supports pinging @users or @roles.
ping_mode
- set to user
or role
- Leave blank to disable pings
ping_id
- set to user/role ID
- Settings > Advanced > Enable Developer Mode to enable Discord developer mode
- Right click user/role > Copy ID
shiny_pokemon_encounter
- Shiny Pokémon encounters
pokemon_encounter_milestones
- Pokémon encounter milestones messages every interval
encounters
shiny_pokemon_encounter_milestones
- Shiny Pokémon encounter milestones every interval
encounters
total_encounter_milestones
- Total encounter milestones every interval
encounters
phase_summary
- Phase summary, first summary at first_interval
, then every consequent_interval
after that
anti_shiny_pokemon_encounter
- Anti-shiny Pokémon encounters
- Anti-shinies are just a bit of fun, they are mathematically, the complete opposite of a shiny
- An SV of
65,528 - 65,535
is considered anti-shiny
Click to expand
A list of shinies to skip catching, useful if you don't want to fill up your PC with very common encounters.
block_list
- list of Pokémon to skip catching, example:
block_list:
- Poochyena
- Pidgey
- Rattata
- Note: phase stats will still be reset after encountering a shiny on the block list.
- The block list is reloaded by the bot after every shiny encounter, so you can modify this file while the bot is running!
Click to expand
Perform actions not possible by a human, such as peeking into eggs to check shininess, knowing instantly which route a roamer is on, instantly locate Feebas tiles etc.
RNG manipulation options may be added to the bot in the future, all cheats are disabled by default.
starters
- soft reset as soon as possible after receiving the starter Pokémon, this will bypass slow battle/menu animations, saving time
starters_rng
- inject a random value into gRngValue
before selecting a starter Pokémon
- Removes all delays before selecting a starter Pokémon, preventing resets from progressively slowing down over time as the bot waits for unique frames
- Gen3 Pokémon games use predictable methods to seed RNG, this can cause the bot to find identical PID Pokémon repeatedly after every reset (which is why RNG manipulation is possible), see here and here for more technical information
- Uses Python's built-in
random
library to generate and inject a 'more random' (still pseudo-random) 32-bit integer into thegRngValue
memory address, essentially re-seeding the game's RNG
Click to expand
The obs_websocket
config will allow the bot to send commands to OBS via WebSockets,
see here for more information on OBS WebSockets.
Enable WebSockets in OBS > Tools > Websocket Server Settings > Enable WebSocket Server
host
- hostname/IP address OBS WebSockets is listening on
port
- TCP port OBS WebSockets is listening on
password
- password to authenticate to WebSocket server (required)
shiny_delay
- delay catching a shiny encounter by n
frames, useful to give you viewers some time to react before saving a replay
discord_delay
- delay Discord webhooks by n
seconds, prevent spoilers if there is a stream delay
screenshot
- take OBS screenshot of shiny encounter
- Note: OBS > Settings > Hotkeys > Screenshot Output must be set to Ctrl + F11
- The bot does not emulate keystrokes, it simply sends a
TriggerHotkeyByKeySequence
(Ctrl + F11) WebSocket command - Screenshot is taken after
shiny_delay
to allow stream overlays to update
replay_buffer
- save OBS replay buffer after replay_buffer_delay
- Note: OBS > Settings > Hotkeys > Replay Buffer > Save Replay must set to Ctrl + F12
- The bot does not emulate keystrokes, it simply sends a
TriggerHotkeyByKeySequence
(Ctrl + F12) WebSocket command
replay_buffer_delay
- delay saving OBS replay buffer by n
seconds
- Runs in a separate thread and will not pause main bot thread
- If the replay buffer is long enough, it will also capture some encounters after the shiny encounter
discord_webhook_url
- Discord webhook URL to post OBS screenshot
, after a shiny encounter
replay_dir
- OBS screenshot/replay buffer folder
- OBS > Settings > Output > Recording > Recording Path
- Relative folder to
pokebot.py
, this is used to post streamscreenshot
to Discord ifdiscord_webhook_url
is set
The http_server
config will enable a Flask HTTP server, which can be used to retrieve data and drive stream overlays.
enable
- toggle web server on/off
ip
- IP address for server to listen on
port
- TCP port for server to listen on
- Port must be unique for each bot instance
All HTTP responses are in JSON format.
GET /trainer
- returns trainer information such as name, TID, SID, map bank, map ID, X/Y coordinates etc.
GET /items
- returns all a list of all items in the bag and PC, and their quantities
GET /party
- returns a detailed list of all Pokémon in the party
GET /encounter_log
returns a detailed list of the recent 10 Pokémon encounters
GET /shiny_log
returns a detailed list of all shiny Pokémon encounters (shiny_log.json
)
GET /stats
returns the phase and total statistics (totals.json
)
GET /encounter_rate
returns the current encounter rate (encounters per hour)
GET /event_flags
returns all event flags for the current save file (optional parameter ?flag=FLAG_NAME
to get a specific flag)
GET /emulator
returns information about the emulator core + the current loaded game/profile
GET /fps
returns a list of emulator FPS (frames per second), in intervals of 1 second, for the previous 60 seconds
- Set TEXT SPEED to FAST
- Set BATTLE SCENE to OFF
- Utilise repel tricks to boost encounter rates of target Pokémon
- Using modes
Spin
orBunny Hop
and repels will become effectively infinite + steps won't be counted in Safari Zone - Use a lead Pokémon with encounter rate boosting abilities, such as Illuminate
- Use a lead Pokémon with a short cry
- Use a lead Pokémon with a single character nickname
- Don't use a shiny lead Pokémon (shiny animation takes a few frames at the start of every battle)
The bot supports auto-starting a profile and can also be launched into a 'debug' mode which can aid bot development.
positional arguments:
profile Profile to initialize. Otherwise, the profile selection menu will appear.
options:
-h, --help show this help message and exit
-m {Manual,Spin,Starters,Fishing,Bunny Hop}, --bot-mode {Manual,Spin,Starters,Fishing,Bunny Hop}
Initial bot mode (default: Manual)
-s {0,1,2,3,4}, --emulation-speed {0,1,2,3,4}
Initial emulation speed (0 for unthrottled; default: 1)
-nv, --no-video Turn off video output by default
-na, --no-audio Turn off audio output by default
-t, --always-on-top Keep the bot window always on top of other windows
-d, --debug Enable extra debug options and a debug menu
Other awesome PokéBot projects:
This project would not be possible without the decompiled symbol tables and other various data from the following projects:
- Pokémon Emerald decompilation (symbols)
- Pokémon Ruby and Sapphire decompilation (symbols)
- Pokémon FireRed and LeafGreen decompilation (symbols)
- PKHeX Plugin: MissingEventFlagsCheckerPlugin (event flags data)