GitHub All-Stars #1: salien-bot

Even after fresh drama connected to being bought by Microsoft, GitHub is still a home for a variety of amazing projects. Each week, a lot of them get community traction. I was observing GitHub trending section for years, seeing many crazy ideas showing up, getting a huge amount of Stars and being forgotten due to new surprise-of-the-week. Some of them are actively developed for a longer period, rest quickly becomes zombified.

Artur Skowroński
GitHub All-Stars
7 min readJun 26, 2018

--

My “collection” of starred projects grew to enormous size, without bringing me (or our community) any value. That’s why I decided to change my approach, bring a bit of regularity there an become a chronicler of all those open source pearls. That’ll allow me to better understand them and to find those I can possibly help with.

Each Wednesday I will choose one trending repo from the previous week and put some attention to it, creating tutorial/article/code reviews, learning from their creators. I’ll focus on whatever gets my interest: it can be tooling, library or anything community decide to be worth being published. I’d go with one simple rule — it needs to be new or unknown projects, not well-known ones, getting a lot of Stars due to some big update.

After that short abstract, we can start.

Salien Main Title

This week I’ll try focus on Salien and some bot created to cheat in it. Three Repos connected to this game are in trending section, with respectively 462, 460 and 130 stars on a time of writing — I decided to describe the first one. But before we’ll go straight to code, probably not everyone knows what Salien is. I’ll resolve that problem quickly.

Saliens is a “game” created for Steam Summer Sale 2018, which started last week. Every player must create his own Salien and defend outposts on planets while playing a shallow shooter game. During strife, the experience is gain and there is an opportunity to win free games to your Steam library. This is standard Valve practice — make people spend as much time as possible on Steam during the promotion period. In the previous edition, there were collectible cards, this time we have a simple game. The simple mechanic is an important thing in the context of this article — a lot of developers are players, and the possibility to win free games is for sure tempting — that’s probably why multiple people try to “automate” the game simultaneously. We’ll take a look on one of the implementations.

It took mere 4 days for meepen/salien-bot to get (at the time of writing) 466 stars, 56 watchers and 149 forks (developers are players, that’s the proof) with 69 closed issues. The author created the bot that helps you get experience and win battles in the game. The impressive part of the project is a fact that it can be run both in Script Mode (with TamperMonkey and ViolentMonkey, GreaseMonkey-style tooling), as well as in Headless mode, using NodeJS. That’s brought my attention — I wanted to check how that both version differs — and now I know they differ a lot.

Let start with the version run in the Browser.

Browser Mode

TamperMonkey icon

Installation with TamperMonkey was blazing fast. The game-script is started as soon as we visit Start Page. We can now leave a game with our Salien killing other aliens and winning games to our collection. Let’s take a look at the source code of the script we run moment ago.

Mentioned script is using *.user.js naming convention used by all clones of Greasemonkey. Thanks to that, it can be recognised automatically by TamperMonkey. which itself is controlled with header definition the file starts with:

That allows to run script only on specific pages. What brings attention is a fact that the script cannot be (explicitly) run with GreaseMonkey:

A great thing in doing a review of greenfield repo is a fact that we can dig up a reason why it was implemented that way: Due to issues with GreaseMonkey, creators decided to drop support for it.

I never wrote such a game bot, so it’s interesting to see how much monkey pathing creators add to make everything run smoothly. There is code injected to automatically reload game on an error, to update score in the custom way or to fix some other minor issues.

But probably the most interesting part is core game logic itself.

Before I started reading the code of the game, I was wondering how attacking enemies was implemented. At first, I was thinking about some interesting visual tracking. The truth is far easier but also probably far more pragmatic and clever:

(a context is in truth window there)

From window object, the whole state of the game is retrieved. Now, event-loop, which is something typical for gaming programming, is run:

With every tick of the original game, Bot is doing following computations:

It’s loading difficulty of the game, which allows him to retrieve a number of enemies that will be spawned.

It’s checking what is current status of the game and if the player is fighting stage game or should choose next planet to defend (for which bot has special logic).

If the player is in the game, enemies are read from the EnemyManager and attacks are executed. There are many possible attacks, which depend on the level of current player:

What’s unusual for JavaScript, they are implemented in the object-oriented way (with quite expanded class hierarchy) and have a simple heuristic in method shouldAttack deciding if given attack should be executed, and on which enemy. If there is the affirmative answer, a mouse is targeting on given enemy and the specific attack is triggered by keycode manager. Additionally, every skill has its own logic and rules — implemented to handle corner cases of every type of action.

Wrapping this section up, Browser code plays the game in a really efficient way, spamming with special attacks and choosing the best-fitted level to play. It’s a rather impressive example of what can be done using UserScripts.

Now it’s time to check second part — headless mode.

Headless Mode

Headless mode is written using Node.js. There is more setup needed to play the game that way — user needs to retrieve the game token from Steam page (which is surprisingly easy). Node app has an only singular dependency which is request.

“Headless” part is a bit confusing there. When I saw the file name like that, I was nearly sure that I will see standard game run in the headless mode of Chrome or Firefox. Nothing different — all communication is performed using Ajax and… faked jQuery.

salien-bot/headless/network.js

Yes, this project contains a module called jquery_node.js. which in internals is just wrapper over request:

salien-bot/headless/jquery_node.js

The first though — unusual design decision :) It’s got even more interesting when I found webapi.js file, which contains 4003 lines of really complex Steam-related code. I couldn’t believe somebody wrote that all in 4 days, so I started digging. What I found after a quick search is that isn’t a file from some different Github Repo but… copy of shared_global.js from Steam site. Probably this strange jQuery dependency is there for compatibility reasons too. Very pragmatic way to make it run very quickly!

That’s also a reason why the headless version of the application doesn’t share any code with browser one. While browser code was controlled by the state in memory, the headless mode is fully Ajax-driven, which change… about everything — in headless mode, there is no playing at all!

After choosing some planet, the timer is started, and after the round ends… request to the server is sent with the precalculated maximum result.

The funniest part of this discovery is the impression that Steam is ok with that’s the whole forgery. It’s proof what kind of promotion-bait whole game is. Being programmed without literally any cheat-resistance…. After running it for an few hours, I’m already nearly maxed with experience — and that doesn’t matter at all — the only thing that counts for the possibility of winning the game is… time spent on the specific planet.

Valve — Masters of Puppets

I will leave my Laptop open for a night. Maybe I’ll win some free games… and probably never even run it once. Sad reality of Steam Sales.

After what we’ve seen from headless mode code review, the whole Saliens game is fighting for your attention with tactics known from the worst freemium-inspired way.

Conclusion

I hope you liked that article. From my perspective, it was captivating to see how bot for such a game was implemented, both as browser script (what allowed me to learn basics of *Monkey) as well as headless mode. It’s also fascinating how faked whole gameplay part of new Steam Summer Sale is. Still, raw amount of community support (167 commits with 20 contributors) proofs one thing — (free) games are something that join developers together.

--

--