Project: Arduino Grid Mouse Clicker (and other Pokemon Go-related fun)

I started my Pokemon Go journey as a “law abiding citizen”. That was, until, someone I knew decided to tell me about this magical thing which could tell me exactly what Pokemon would spawn in front of me at any given time. To prove it wasn’t a joke, we compared notes between what I saw, and what he saw (even though he was nowhere in my neighbourhood). Ultimately, the notes matched up, and after a while he fessed up about his “little secret” – a service known as Pokevision and various scanning tools such as PokemonGo-Map.

Because I was too busy to be playing and wouldn’t be heading out for a few days, I decided to take a peek into the world of Pokemon Go through these services. I wondered whether there were any particular spawn patterns, what the relative spawn frequencies were, was Team Instinct really the “least successful” team, and just what the gym to PokeStop ratio was. Data is always interesting.

As a result, I spent about a day on the 27th July scraping data by various means to see exactly what would turn up. While using Pokevision meant that they would do the scanning for you, and you would be indirectly contravening the terms of service, using direct scrapers meant a good chance of a ban. Of course, by then, it was only a matter of days before Niantic instituted countermeasures to stop people from scanning, and sent cease and desist notices which took down the services. All in all, I never really benefited from the whole “scanning” craze – it had all wound down by the time I actually could get out of the house and I felt a little jealous at all the gyms around me with CP2400+ Dragonites guarding them … when I didn’t even have one to call my own.

It’s clear from the recent ban waves in the Pokemon Go community that Niantic doesn’t tolerate cheaters using GPS spoofing, bots or scanning using unapproved clients. Such activities have caused a lot of server load which impacts on the game’s launches and operation, and is considered unfair. I fully understand and respect Niantic’s wishes, and continue to play the game honestly without pursuing any such “workarounds”.

The Need to Click

My first experiment was using the Pokevision service. This basically allowed you to scan for Pokemon within a certain radius of a position specified by clicking your mouse. Scans are “limited” to 30 seconds, but I found that whenever I clicked “elsewhere”, a scan was immediately run and results returned while old results were cached. In order to scan a wide area, I would need to zoom out on the map and continually click around the Sydney basin. If I had to do this by hand … it wouldn’t be very scientific or enjoyable.

So, I decided to use something I had on hand, namely an Arduino Leonardo. I called the program arraymouse and it relies on the Mouse library within Arduino. As this requires the emulation of a USB HID (Human Interface Device), this requires the use of the Arduino Leonardo (or equivalent, such as the Freetronics Leostick) as it has a “native” USB interface on the ATMEL AVR microcontroller.

2016082323198292

The other units are generally built around UART chips which can only act as a USB CDC (Communications Device Class) serial converter, or an AVR chip programmed to do that (which can be modified if you manually reprogram it using the ICSP pins, but that’s hardly convenient).

#include <Mouse.h>

#define GRIDWIDTH 24
#define PAUSE 500
#define XWIDTH 640
#define YHEIGHT 400

int xpos=0;
int ypos=0;
int temp=0;

void setup() {
   pinMode(13,OUTPUT);
   delay(5000);
   digitalWrite(13,HIGH);
   Mouse.begin();
}

void loop() {
  while(ypos<YHEIGHT) {
    while(xpos<XWIDTH) {
      if(!(xpos%GRIDWIDTH)) {
        Mouse.click();
        delay(PAUSE);
      }
      xpos=xpos+1;
      Mouse.move(1,0,0);
      delay(20);
    }
    while(xpos){
      Mouse.move(-1,0,0);
      xpos=xpos-1;
      delay(20);
    }
    temp=0;
    ypos=ypos+GRIDWIDTH;
    while(temp<GRIDWIDTH) {
      Mouse.move(0,1,0);
      delay(20);
      temp=temp+1;
    }
  }
  while(ypos){
  Mouse.move(0,-1,0);
  delay(20);  
  ypos=ypos-1;
  }
}

With such a program, depending on the parameters given, you can basically make it move the pointer in a grid pattern and click once in each spot. The perfection of the grid is so uncanny – a human can’t do this. This was done with the Leonardo hooked up to the USB port and Photoshop open with a brush-tool selected.

scangrids

The important thing to realize is that it is “emulating” a mouse, and that is not exactly straightforward. Depending on the mouse driver, there are several quirks to be aware of:

  • One mouse movement does not equal one pixel movement on the screen. This actually depends on the mouse pointer speed as set in the driver/Control Panel.
  • One mouse movement of 10 units might not equal ten mouse movements of 1 unit. This happens especially if the driver has pointer acceleration enabled which means that larger mouse events/events spaced closer together have a non-linear multiplier effect.
  • There’s no way to know where your pointer is starting from, if it’s bumped into the edge of the screen, or if it’s come back to a certain place. You are literally driving blind.

As a result, it pays to experiment somewhat and get the values tuned to your needs by altering, reprogramming and testing. Leaving your mouse in an initial position is necessary, to ensure the right results. Note that any positional differences will “add up” over time, so to have a scan grid that works over long periods, it’s important to check the pointer never “bumps into” any edges of the screen.

You can also use the Mouse library to do mouse jiggles, and perhaps drive people insane. There’s a corresponding Keyboard library as well which lets you go and send keystrokes to the connected computer, which could come in quite handy.

In my case, I was running a little experiment to try and see whether there were any spatial patterns for the spawn of Eevee and its evolutions. To do that, I ended up using a screen recorder and altering the frame-rate to accelerate the playback so that a whole 4.5 hour observation can be seen in a minute and a half. The system wasn’t too happy and the browser eventually crashed because it ran out of memory, because Pokevision was filtering the icons on the client side (and it was literally plotting all of the spawns in the Sydney area “transparently”). It would seem from the video that there definitely are preferred regions, and its evolved forms do very sporadically appear. Sadly, where I am, it’s a total quiet-zone with no activity at all.

Pokevision was free, easy to use and popularized scanning for a large percentage of the userbase. It has since been offline for a long time, and is not likely to ever return.

The Scan-alysis

Not content with this, I decided to go one step further and cross the boundary into danger. Yes, I broke the terms of service, and it’s probably not the first time I’ve done something nasty like that. I figured, if it’s for my own curiosity, it can’t be too bad. As a result, I decided to set up a Ubuntu VM, install the necessary packages, scratch my head as things didn’t work out and solve a few package issues with Python. Only after that, and some further tinkering, did I managed to run a few instances of PokemonGo-Map over a day to capture some data for later analysis.

Please remember that the data was collected 27th July 2016, and is thoroughly out of date by now. Things are likely to have changed, so it really is only for historical relevance.

sydney-area

With a wide scanning area run only once or twice, I managed to find a few interesting results:

  • Gyms are in blue, Pokestops in grey. It seems the Gyms are roughly evenly spatially distributed, but Pokestops are densely clustered in the city, and rarely found around where I am (bottom left corner of the map).
  • There are approximately 5.944 PokeStops per Gym in the scanned area.
  • 139 types of Pokemon were observed to spawn in the scanned area, which is only 4 less than the number of available Pokemon to catch (145 total available as the three legendary birds, Ditto, Mew and Mewtwo are not released; and minus three regional exclusives not in Australia, namely Farfetch’d, Tauros and Mr. Mime).

pogoscan-gymown

  • Of the gyms, Valor and Mystic hold an almost-even split, which leaves Instinct at half the number of either one. [Insert sad-face]

pogoscan-gymguard

  • In terms of Gym guard Pokemon, Exeggutor, Dragonite, Vaporeon take out the top three positions with a combined percentage of 44.2% (or close to half the gyms).

pogoscan-relative-frequency-pie

  • In terms of spawned Pokemon, you’d be right to be annoyed if you saw a Zubat, Doduo, Pidgey, Weedle or Rattata, as they comprise over 50% of all spawns observed. I suppose I was right when I said my neighbourhood had a Doduo problem.

pogoscan-frequencies

  • A full list of relative spawn frequencies are shown above. Apologies for the confusing way it is plotted – bars run from right to left, the longer the bar, the rarer the Pokemon. Each division indicates a 10-fold increase in rarity (log-scale). Steps appear in the data owing to the “quantization” of spawn (i.e. spawns are integer).

Needless to say, by the next day, it seemed that the games were all over and countermeasures were put into place to make this type of scraping more difficult or even impossible. As a result, I quickly lost interest in the whole project and shelved it, declaring the whole thing “dead” as it was clear to me that Niantic didn’t want us doing it.

Conclusion

With an Arduino, it’s relatively trivial to emulate a mouse and cause it to click repeatedly in a grid pattern to do some scanning. Good to know if you ever run into a need for such a thing and just want to “get it over and done with” in hardware, so that it works almost universally.

The data in this article is mainly provided for historical relevance. None of the services are available anymore, direct scanning has been blocked by various means and isn’t a really viable route anymore. I didn’t actually do much but scrape some data and analyze it – I never got to catch any Pokemon as a direct result of the data.

In fact, from what I have observed playing the game is that the patterns that may have been previously established, and the frequency of encounters, have changed dramatically with tweaks to the game at Niantic’s end. Where some Pokemon were very rare and never seen in my travels (e.g. Kangaskhan), just in the past week, I’ve walked into four. As a result, the data that’s provided really was only valid back then and isn’t in any way representative of the game in its present state.

So, in the end, I have to thank Niantic for bringing me a whole lot of fun, a reason to go out, and maybe even help me get a little more healthy while enjoying myself. It’s been the best motivation by far – better than any fitness tracker, and I’ve tested quite a few. Sorry for the added server load for a day – I promise I’m not doing any more of this and haven’t been since the first wave of countermeasures was launched.

After all … when I signed up to be a Pokemon Trainer … I kind-of agreed to:

“I will travel across the land,
searching far and wide …”

rather than pretending to travel across the land … by clicking far and wide. As a result, even though I see less people playing since the bans, and lots of people whining about a dysfunctional tracker … I suppose the thrill is in the serendipity of a Pokemon encounter. Remember, the motto is “gotta catch ’em all,” not “got to catch the nice ones only.”

Stay safe fellow Pokemon Go-ers, and go Team Instinct!

About lui_gough

I’m a bit of a nut for electronics, computing, photography, radio, satellite and other technical hobbies. Click for more about me!

This entry was posted in Computing and tagged , , , , . Bookmark the permalink.

2 Responses to Project: Arduino Grid Mouse Clicker (and other Pokemon Go-related fun)

  1. septfox says:

    You may have figured this out already, but Pokestops and Gyms are (or at least appear to be) placed at PoIs/Portals pulled from Ingress’ database.

    I don’t know if/when they refresh placements, but it may be possible to create new Pokestops around yourself by “discovering” places that Niantic would agree are historically relevant or at least mildly interesting.
    Gym placement, on the other hand, I would imagine relies on some special conditions being met; perhaps needing to be X distance away from other Gyms and within Y of Z other Pokestops (to prevent them from being spawned in the middle of nowhere next to a Pokestop in a cemetery or something). It would be an interesting experiment to find an “untouched” town or something and populate it with portals, see what the reaction in GO is if any.

    • lui_gough says:

      Indeed, the links to Ingress were known days after the launch, but it was found that only 50% of portals were transferred as POIs in Pokemon Go. As to whether a portal would become nothing, a Pokestop or a Gym was a bit baffling, and as I wasn’t an Ingress player and couldn’t be bothered to sign up just to view their map, I never bothered.

      Instead, the plot I made was a byproduct of the scanning algorithm – as it pulled all the data from the servers, that included the Pokestop/Gym/Guard Pokemon data, so I decided to use it anyway just to see what the spatial distribution looks like. Some people have mentioned that they have requested new stops in sparse locations using their support forms, whereas others have mentioned a few (occasional) successes in deactivating stops where overcrowding became an issue, so everything is “fluid” and can become out of date. I would suspect that any changes to each game might be handled semi-independently, mainly because Ingress players might be annoyed when their portals start disappearing because of bad Pokemon Go players and vice versa. After all, Ingress had been running for years and never caused any “real” trouble because of a much smaller userbase.

      There are quite a few places where there just isn’t data. Apparently South Korea is mostly uncovered for example, but apparently that also has to do with Google Maps service provision issues (maybe governmental related).

      – Gough

Error: Comment is Missing!