Auto-Hunting Shiny Pokemon
A guide on how I would shiny hunt a perfect Gengar
by Jason Heflinger
Disclaimer
To start off with, this is a HYPOTHETICAL situation that I DEFINITELY DID NOT ACTUALLY DO!! Any pictures you see here are DEFINITELY PHOTOSHOPPED and I do NOT condone abusing technical prowess to gain an advantage in an online fan pokemon game. This post is purely to speculate on how to approach such a problem as a technical challenge, and any language that suggests otherwise from this point onwards is purely due to me getting into the mindset of the situation.
Motivation
So assuming that I am indeed playing a game called PokeMMO, in which generations 1-5 are all combined into a cohesive MMO world that players can interact with, my goal is to get a shiny Gengar, preferrably with perfect special attack and speed IVs for an ideal glass cannon build. To do this, I'm going to need to get at least 1 shiny gastly with a perfect special attack IV, and one shiny gastly with a perfect speed IV, with each one being an opposing gender.



Marketplace for Shiny Gastly

And yes, while there is a marketplace in PokeMMO where I could theoretically buy these, that defeats the spirit! The goal is to automate organically getting this shiny Gengar, as hypocritical as that seems.

You may also ask, why shiny GENGAR? Isn't the shiny for it pretty bad? And to that, I say yes! It is bad! A travesty to how awesome Gastly and Haunter look while shiny! But alas, my favorite pokemon is still Gengar, and I guess I can always install a mod to upload a cooler shiny sprite for it...
Challenges
Ultimately, my challenge is to find a way to automate user interaction to use the PokeMMO application to spam encounters until I find a shiny gastly.

So first off, the biggest oof is that in PokeMMO, the chances of finding a shiny is 1 in 30,000!!! For reference, modern pokemon games have a 1 in 4096 chance to find a shiny given an encounter, so I'm gonna need to be over 6 times luckier to land a shiny...

On the more technical side of things, since this is technically not allowed, it's not like I have access to an API to do this concretely. This means I'm gonna have to just emulate user interaction into the application to do my automations. Not only this, there is some randomness in between actions when scenes have to load, since this game is on the network.
Setup
To start off with, I had to find the perfect environment to do this in. This means for one, I'm going to have to find a spot with ideally as many gastly as possible, at all times of the day. Secondly, I'm going to have to reduce the amount of steps in between the battleground and a pokemon center as much as possible. This is because I'm going to be using sweet scent! In PokeMMO, sweet scent can be used to instantly encounter a horde of 3-6 pokemon, depending on the area you are in. With maxing out PP, I can use sweet scent about 6 times before I have to refresh at a pokemon center. Since I no longer have to waste time running in the grass, and I get 3-6x more encounters, this is definitely worth the trip to the pokemon center.



Pokemon Tower

Luckily, there's a spot in the Kanto region that nearly perfectly satisfies this requirement! The third floor of Pokemon Tower in Lavender town! It has exclusively gastly at all times of the day, and the pokemon center is right outside! Unfortunately, the hordes from sweet scent are only of size 3, but this is more than good enough to set up camp.

And lastly, we just need our oddish with sweet scent, a PP max, a smoke ball, and an electrode with a max IV for speed to garuntee that we can run away from every encounter. Easy, just a simple investment of around... 52,000 pokedollars. Ouch, thats a dent in my wallet. We're not gonna talk about the fact that I thought you could have multiple pokemon with sweet scent and how I spent 180,000 buying Oddish with sweet scent...
Using a macro recorder
To start off with, I tried just recording one round of sweet scent and a pokemon center trip using a macro recorder app. For the most part, this worked quite well! All I had to do was start the recorded macro, and then just watch the encounters to see if any of them were shinies. However, the only free non-sketchy macro recorder app out there that I could find was Macro Recorder, which has a limit of like 10 automatic repeats. To get around this, I just copy pasted my macro like 100 times into one big macro, and then repeated that 10 times to get a total of 1000 repeats. Silly, I know. But then, I had the realization of the century - why the hell am I relying on this app like some sort of plebian? I'm a programmer! If there is something I want to automate, I should spend a month programming a perfect automation myself! And so, that's exactly what I did.
Switching to python
Turns out, python has a nifty little library called pyautogui that can pretty much handle emulating user input. This makes it really easy to make a simple automation program. By just reading in a script file, I can then take simple commands such as click left 100 100 and translate them to actual events. I can then convert the macro library macro to our new script format, and then add a loop command to make it loop for as long as I want!
Removing User Observation
So there's one last issue with this approach before it is truly automated - I still have to keep watch of the encounters to look out for the shiny. I don't have a way of automatically stopping the script execution when a shiny appears! To remedy this, I've added a colorcheck command to check for a specfic color in a given screen region.



Colormasking a Shiny Gastly

This command just uses a basic mask to filter out any pixels that aren't the specified color, and then just flattens and checks the overall value of the frame to see if it is significantly positive or not. Then I can just input the blue color of the shiny gastly, and that command will then quit the script when it detects a shiny!
Supporting Remote Control
Now, while this works, it can still be better. Primarily, what I don't like is that PokeMMO has about a 15 minute AFK timeout feature. This means that if the script finds a shiny while I'm out and about, I have to be back to see it within 15 minutes or else I risk logging out and missing it. This is quite annoying, since I don't like just having a slight overhanging feeling of hope constantly throughout my day.

The first solution to this is to register for a google voice number, open the account in my browser, and then have the script switch to that tab and text me that it has found a shiny. This way, if I'm out and about I'll be able to recieve a text notification that I've found a shiny and then proceed to log in remotely on my phone to catch it. However, this isn't a perfect solution; there are still 2 problems. The first problem is that at this point in time, I'm still a student! For the most of my day, I'm still in class where I can't exactly check my phone visibly without disrespecting the lecture (I go to a pretty small school, usually like 20-30 students a class). The second problem is that the script overall is not the most reliable of all time. There are times when the inputs are a bit too late due to network lag, which causes the player path to be out of sync. From here the player can walk around to different areas accidentally, encountering new pokemon, and waste time or accidentally trigger the text notification.



Stuck on Floor 2

The final solution to all of this is two way communication via Discord (the messaging app). By having the script also monitor the last message of a Discord chat, I can analyze the colors to check for the 🟥🟦🟩🟪 emojis and use them as commands to have the script do different things without needing to create my own OCR library. The commands do the following:
  • 🟦 means to send a screenshot so I can monitor the progress of the gameplay and ensure that nothing has gone wrong
  • 🟪 means to pause the script execution, so I can possibly remotely log in and correct the positioning of the player
  • 🟩 means to continue the script execution after a pause
  • 🟥 means to quit script execution
Using these commands, I can then send a screenshot and pause when I find a shiny, monitor this chat in class while on my laptop, and then check in every once in a while to ensure things are going well!
The Prize
Now after all this anticipation, I just have to let this bot run every day during waking hours! At a rate of about 18 encounters every 1.5 minutes for 10 hours a day, thats about 8,640 encounters a day! With enough luck, a shiny should appear about once every 3 days. However, days had come and gone. For an entire week and a half. For 140,000 encounters. The likelyhood that I should've encountered a shiny by now is, well, errrrr, 1 minus 1 minus one over 30 thousand to the power of one hundred fourty thounsand... uhhhhhh... 99.05971776%?!?! Is something wrong? Did I miss one? Is my color check command not working? There's no real way to exactly test this perfectly without seeing it find a shiny and not run away from it right before my eyes. All I could really do was trust my fake tests, and hope and pray that I've just been REALLLLLY unlucky so far. And lo and behold, 147,121 encounters in, we FOUND IT!! (Although it's only good IV is attack...)



The First Useless Shiny

After this, thankfully, it only took about 2,000-8,000 encounters for the next several shinies, and they all had either perfect special attack or speed! With a little fiddling to get the genders correct, the final perfect gastly was born, trained, and evolved into the glass cannon of all time:



Gengar

Overall, this was probably far too much work for a silly little Pokemon game, but it was very fun to do! This post makes it sound pretty damn simple and easy, but it definitely was not. In between all these solutions, there was a lot of trial and error, realizing that I might be missing out on shinies, more testing, more trials, more realizing a day in my bot broke, and more. While the working final product ran for about 2 weeks to get all the shinies, the gross time I sunk into this project was about a little over an entire month. I probably won't use the program again since it feels a little unethical to abuse, especially since each of these gastly are worth at minimum about 4 million pokedollars, which would really flood the market and possibly cause some shifts. All I truly needed was my shiny gengar, which thankfully I did not do myself since it would've taken roughly 200,000 manual encounters to do apparently before I'd have found it...