Introduction
A close friend of mine has a tendency to recommend games to me on Steam with easy or really trivial achievements. This makes it really easy to get all achievements. Recently, she recommended me a game called Bongo Cat, which simply monitors your button presses/mouse clicks and increases a counter. It's literally just a "numbers go higher" game. It has 7 achievements on Steam. The highest one requires 1 million presses. I'm not too concerned with hitting that manually. But I wanted to have some fun with this.
I am a computer scientist. One of the fun parts of the hobby is finding out how other software works and trying to break it. To me, that's fun. It isn't to cheat (even though it literally is cheating). It's a puzzle to solve. Every game has their quirks and I just like breaking them or writing a bot to automate it. No one said I can't do that. I've been a game developer before. So I am no stranger to this.
This will be a quick one. So let's get to it. Just for old times sake, I will be using Game Maker 8 Pro to bust this game wide open.
The Initial Attempt: A single button press
My first point of attack was simple. Simply repeatedly press the same button over and over again. Game Maker supplies functions for doing just this:
-
keyboard_key_press
- Simulates a key press -
keyboard_key_release
- Simulates a key release
With those in mind, we can simulate keyboard presses on the keyboard by
simply calling both functions with a slight delay between them. Since
we are using Game Maker 8, we can use the sleep
function to
temporarily pause the game giving Bongo Cat enough time to register the
key press.
I also want the bot to have some switch of some kind so I can turn on and off the button presses at will. Let's have the space button do that. So with that, let's make a room, followed by an instance. Then in the Create Event, do this:
sw = false;
The Create Event is called when the object is created, obviously. It will
simply set up variables. I want the bot to only spam a button when
sw
is set to 1
. The rest of the code will be in
the object's step event, which occurs at every single frame.
if (keyboard_check_pressed(vk_space)) {
if (sw == false) {
sw = true;
}
else {
sw = false;
}
}
if (sw == true) {
keyboard_key_press(ord("V"));
sleep(25);
keyboard_key_release(ord("V"));
sleep(25);
}
The result? Well... technically it works. Here's an animation of it:

That speed is just unacceptable though. How are we supposed to hit 1 million at that rate? Turns out, Bongo Cat has checks in place to account for speed rate for a singular button pressed. This is why I chose a sleep time of 25 milliseconds. If it's faster, Bongo Cat will not recognise the key press. If it did, we could have just ramped the FPS up in Game Maker, removed the delay entirely, and the counter would have skyrocketed.
As always with these blog posts, we can do better. Much better.
The Better Attempt: A queue system
Remember how I stated earlier that Bongo Cat has checks in place to account for the speed rate of a singular button pressed? I said "singular" for a reason. If you press multiple keys, it will register them regardless of how many frames or milliseconds have passed. I did not reverse-engineer the game's code to figure this out otherwise this blog post would have got the "Reverse Engineering" tag.
Anyway, we need to write up a small system that will allow us to press multiple keys back-to-back, and then release them in the same order. This requires a queue data structure. For those of you in Computer Science, this is a FIFO data structure (first-in, first-out). So we press a button, log it, check the queue, release the key.
If this were C or C++, a queue is trivial to code. But this is Game Maker.
So we have arrays. Sure, there's
DS Queues,
but I want this code to be extremely simple. So let's use an array, and
keep track of positioning for when a key is pressed or released. This
requires 2 index integers. One for keeping track of the rear side of the
queue that we insert in (queue_press_pos
), and one for keeping
track of the front side that we pop off (queue_release_pos
).
Arrays in Game Maker are sized 32000x32000. Let's ignore that and assume a
fixed size of 1000. Then, when that's exceeded, simply wrap back to 0.
sw = false;
key_len = 1000;
queue_press_pos = 0;
queue_release_pos = 0;
key_queue = 0;
key_ts = 0;
frame = 0;
var key;
if (keyboard_check_pressed(vk_space)) {
if (sw == 0) {
sw = 1;
}
else {
sw = 0;
}
}
if (sw == true) {
// Generate key and put it in the queue
key = ord("A") + floor(random(ord("Z") - ord("A")));
key_queue[queue_press_pos] = key;
key_ts [queue_press_pos] = frame;
queue_press_pos += 1;
// Press the key
keyboard_key_press(key);
sleep(1);
// Advance the frame
frame += 1;
// If 26 frames have passed, release the button
if (frame > key_ts[queue_release_pos] + 26) {
keyboard_key_release(key_queue[queue_release_pos]);
queue_release_pos += 1;
}
// Wrap around
if (queue_press_pos > key_len)
queue_press_pos = 0;
if (queue_release_pos > key_len)
queue_release_pos = 0;
}
A random key between A and Z is chosen to be added to the queue. It is
pressed. 26 frames later, that key is released (actually, it's 25 since
the frame
variable advances mid-step). When both indices
exceed key_len
(1000), it wraps back around to 0. This
covers everything and allows for a key to be pressed every single
frame.
In hindsight, there's probably a +1/-1 error in computing the keys to press. But I don't care. Because watch what happens when I execute this code:

That's more like it! Now I just have to let it sit there for a while and it will eventually hit 1 million. Thanks for the free achievements.
Source Code and Executable
I wanted to give access to the source code so people with Game Maker can look into how this works. It's simple enough that there really isn't much need to even post a source code file. But I did so anyway. Also, if you trust a random woman on the Internet, I will also provide an EXE you can download and run to do this yourself.
- Source Code (9.4 KB)
- Executable (2.3 MB)
- Game Maker 8 Logo (Recreation) [201 KB]
There you go. I even included the Figma recreation of the Game Maker 8 logo that was used in the banner of the blog post. It's vectorised. You're welcome.
Closing remarks
This was a fun little puzzle. Something really simple to write about. Back then, I used to write bots with Game Maker all the time for games. So it felt good getting back into it. This game was a very simple one. But in more complex games, you will need C/C++ DLLs to control the mouse, as Game Maker doesn't allow you to simulate mouse clicks for some reason. Maybe later on, I will write a blog post showing how to break Bongo Cat in C/C++. But for now, I wanted to go back to my roots a bit and enjoy Game Maker. It's more than for games. It can be for writing tools as well.
I guess lastly, I know it's possible to use Cheat Engine to change the game's memory internally and force the achievements to pop up. While that kind of effort may be fun to some, I wanted a solution utilising an old tool from back in my game dev days. There's more than one correct answer to solving a puzzle sometimes. And I encourage you to seek your own creative solution.