P
PyBoy4mo ago
scudfpv

Help on Debugging a Bot for Pokemon Red

Hi guys, I'm new here. Also, programming is a hobby, so please don't evaluate the code as a real programmer. Attached is the code and requirements I'm using to create a bot so I can accelerate the speed of leveling up. In summary, the code reads the flags from text files where I toggle "y" to activate the features. The main feature is the training, where the character goes from left to right in a zone where there are wild pokemon. If HP or PP are zero for the 1st pokemon in the party, then it goes to the pokemon center. The path to pokemon center was previously recorded based on X, Y and Map ID and saved in another log file. Issue: the bot works as expected (levels up ~10 levels) until some point where it gets stuck after PP=0. Instead of going to the pokemon center, it goes left, hit the wall, and there is this infinite loop. I tried the best I could to debug what could happen, but I think it is time to get some help from experts. Any hint on what I could do different, I'll appreciate. Disclaimer: I'm using Pyboy 1.6.9 because I got issues with other dependencies in the new version and it crashed a lot, so I gave up and focused on the version that was working.
11 Replies
Bækalfen
Bækalfen4mo ago
It's a thousand lines of code, so I cannot give you precise answers on what it does wrong. But I skimmed through your code and noticed a few things: Your function move_left_right is unused, but it won't work as you're sending:
pyboy.send_input(WindowEvent.PRESS_ARROW_LEFT)
pyboy.send_input(WindowEvent.RELEASE_ARROW_RIGHT)
pyboy.send_input(WindowEvent.PRESS_ARROW_LEFT)
pyboy.send_input(WindowEvent.RELEASE_ARROW_RIGHT)
Within the same frame. So the game will never notice that it was pressed. The function follow_reverse_path_from_file doesn't exist, so your script will crash once you call go_to_poke_center. In go_to_position you don't define res, so again your script will crash. You have a lot of patterns like this:
pyboy.send_input(WindowEvent.PRESS_ARROW_DOWN)
for _ in range(tick_range*3):
pyboy.tick()

pyboy.send_input(WindowEvent.RELEASE_ARROW_DOWN)
for _ in range(tick_range*3):
pyboy.tick()
pyboy.send_input(WindowEvent.PRESS_ARROW_DOWN)
for _ in range(tick_range*3):
pyboy.tick()

pyboy.send_input(WindowEvent.RELEASE_ARROW_DOWN)
for _ in range(tick_range*3):
pyboy.tick()
You should put that in a function so you Don't Repeat Yourself (DRY). This will make it easier for you to spot errors, as you can exclude where the issue can be. I'd recommend you find a good editor like VSCode and install the Python plugins. It'll highlight many of the issues I point out. Although it's maybe not the answer you want, but it's how you best locate mistakes. Also, learn how to set breakpoints in VSCode and step through the code at the point that you think is flawed. There's probably tutorials on YouTube that'll show you how
scudfpv
scudfpvOP4mo ago
thanks for the fast response, and that is a great advice. That what I was expecting, some best practices. It wouldn't be fair to expect someone to read thousand of lines and right spot the issue. I used python for analytics, and I was using Spyder for debugging. I couldn't use Pyboy with Spyder so I was using Notepad++, but I believe VSCode will be a lot better. Additionaly, one question regarding Pyboy fast fowarding. Is there a way to adjust speed? Also, is it possible that the speed could affect the run? e.g. some part of the code can be skipped at random due to speed? in fact, this question does not make sense for me but I noted I added some interrupts, meaning toggling "y" and "n" in bot_trained_enabled, then the issue disapear. But of course it is not robust.
Bækalfen
Bækalfen4mo ago
You can set the speed however you wish. The outcome is guaranteed to be the same https://docs.pyboy.dk/#pyboy.PyBoy.set_emulation_speed
scudfpv
scudfpvOP3mo ago
@Bækalfen , I did some work using VS Code and helped a lot.Attached the updated code on 1.6.9. Now I'm trying to move from pyboy 1.6.9 to the latest version, but I'd like to use the state file from 1.6.9. I generated a "ram" file and would like to read that using pyboy 2.6.0, as read the state file is not possible. Any hints on how to do, please? I didn't find a "load .sav/ram" in 2.6.0 documentation.
Bækalfen
Bækalfen3mo ago
It automatically loads the .ram file It should be placed next to the ROM
scudfpv
scudfpvOP3mo ago
I did the test cases from the file attached. I couldn't load the 'ram' file or 'sav' file into the pyboy emulator. However I could successfully load the state file from 1.6.9 in 2.6.0. However, the fact that I'm not loading the 'sav' or 'ram' file, maybe it is related to the fact that I'm not being able to load it in any other emulator as I mentioned in this topic: https://discord.com/channels/584149554132418570/1363386169181733085 any hints?
Bækalfen
Bækalfen3mo ago
I don't want to open a bunch of files from someone I don't know. Could you post your findings here?
scudfpv
scudfpvOP3mo ago
I'll place the image from excel file
scudfpv
scudfpvOP3mo ago
No description
Bækalfen
Bækalfen3mo ago
Your mistake is in 5 and 8. Somehow you're not placing the files the right place or with the right name. Proven that it works in 1 and 2.
scudfpv
scudfpvOP3mo ago
it worked in 1 and 2 because I'm reading the 'state' file and exporting to 'ram'. However, in 5 and 8, I tried to read 'sav' file in 2 different ways: 1) rename 'ram' to 'sav' and place in the same folder of the 'rom'. Load 'rom' in the emulator so it reads automatically the 'sav' file. -> failed 2) rename 'ram' to 'sav' and use use the import command from the emulator. Then I select exactly the file that I want. In this case, I can import only 'sav' or 'dat' file. 'ram is not allowed. Also, it failed. Question: is there a way to read and compare the 'sav' file from the one I renamed from 'ram' and the other that is exported from the emulator (non-pyboy)? now it worked. I was running this code:
# Initialize PyBoy emulator 1.6.9
pyboy = PyBoy(ROM_PATH, window_type="SDL2")

# Load game state
with open(STATE_PATH, "rb") as f:
pyboy.load_state(f)

# Main loop
while not pyboy.tick():
pass
pyboy.stop()
# Initialize PyBoy emulator 1.6.9
pyboy = PyBoy(ROM_PATH, window_type="SDL2")

# Load game state
with open(STATE_PATH, "rb") as f:
pyboy.load_state(f)

# Main loop
while not pyboy.tick():
pass
pyboy.stop()
it generated the 'ram' file, but was not read by the emulator. When I did the 'in game save' before closing the pyboy emulator, then the 'ram' file converted to 'sav' was read in the emulator. To sum up: run pyboy -> read state -> do in-game save -> close pyboy -> rename 'ram' to 'sav' -> read in the other emulator thanks for the comments @Bækalfen , they made me redo all the steps until find the solution.

Did you find this page helpful?