I am a long time fan of Blizzard’s collectible card game Hearthstone: Heroes of WarCraft, and I figured I’d try to combine two interests of mine together and do some data analysis and dig into the question of just what is the best neutral four cost minion (aka 4 drop) in the game.
In this post we will look at a way to model interactions between hearthstone minions to estimate bang-for-buck when it comes to minion trading. In particular we will use simulation and a simple model of minion interactions to explore one way to go about answering this question. The full code for this analysis is in this python notebook in case you want to dig into how this was done.
What is Hearthstone?
First some preliminaries; what is hearthstone and aren’t minions earnest, pill-shaped, yellow cartoon characters with a minor penchant for evil? I’ll let this fairly dramatic trailer provide a sense of what kind of game this is.
If you’ve had some past experiences playing physical collectible cards games then I’d briefly describe it as a simpler, funner, streamlined digital version of Magic: The Gathering. If you don’t know what that is… Well let's just carry on.
The basic gist of the game is to play cards representing creatures (called minions) to the board, where they can attack the enemy minions or enemy hero in future turns. You can also play spells which have immediate effects on minions or heroes. The goal of the game being to bring the enemy hero’s health down to zero!
Relevant for our purposes today is a basic understanding of how minions interact with each other in hearthstone. Take the two cards below.
Each minion has a mana cost in the top left corner, an attack strength in the bottom left corner and health in the bottom right. Mana is the precious and limited resource you spend to summon these minions and cast spells and you only have a fixed amount each turn. You start the game with 1 mana per turn and each turn that grows by 1 mana to a maximum of 10 mana per turn to spend in the later turns of the game.
Both these cards are considered neutral minions because they are available to all hero classes in the game (i.e. anybody can use them). To keep things simple this post is focused only on neutral minions. If you are starting the game, these are minions you have fairly easy access to.
When one minion attacks another, it defeats it if its attack strength is greater than or equal to its opponents health. The attacking minion also dies if its health is lower or equal to opponents attack strength.
So if the Oasis Snapjaw attacks the Bloodfen Raptor, it will kill the raptor and have
(7-3) = 4 health left over. Wow, it looks like that snapjaw can defeat 3 little dinos all by itself! Easy candidate for being the best card in the game right? Well, maybe not, there are hundreds of minions in the game and thousands of interactions like this to sift through. Also the snapjaw costs twice as much mana (a precious resource indeed), so we would expect it to be better than the cheaper 2 cost raptor. Is it really that good given its cost?
A Model of Minion Efficiency
We can dive into this question using the venerable Chillwind Yeti as our guide. In the early days of hearthstone, the Yeti was practically a must have in your deck (it is also free!); it has decent health and does a good amount of damage, but can we build a ranking of minions in that cost 4 mana for comparison?
The approach I took in doing this was to try and calculate an efficiency score for each minion with regard to interactions with other minions. Let's get a little bit more terminology out of the way as we introduce our model.
- A minion trades evenly with a minion if they are of the same cost and both die in the interaction. This is par for the course.
- A minion trades up with a minion if both die but the opposing minion is more expensive (e.g. a 2 mana minion defeating a 3 mana minion). This is pretty good!
- A minion trades down with a minion if both die and the opposing minion is less expensive. This isn’t terrible, but isn’t great either.
- A minion wins against another minion if it survives the attack but the other minion does not.
- A minion loses to another minion if it does not survive that minion's attack, and also fails to kill the attacking minion.
- Winning up thus signifies defeating a higher cost minion and surviving; this is especially good. Up, Even and Down specify the mana relationships for winning and losing in the same way as described above for trading.
Here are those interactions in table forms, with point values assigned for each one. Note that penalties are expressed as negative points. Where do these points come from? Well they are completely arbitrary; however they do capture my intuition of the relative value of these interactions based on my experience of the game. When we construct our model, we can revisit these values to tune the result if we want to prioritize for more defensive or more aggressive minions.
|Interaction||Value (in points)||Notes|
|Trade Down||-0.5||Was out-valued by lower cost minion|
|Lose Up||0||Lost to a higher cost minion, no penalty.|
|Lose Even||-1||Was out-valued by equal cost minion|
|Lose Down||-2.5||Lost outright to lower cost minion.|
You can see the function that implements this in the python notebook
Minion Efficiency Scores
Using the model of minion interactions described above I simulatated each neutral minion in combat against against all other minions of equal cost, as well as minions of 1 lower or 1 greater mana cost. Why these ranges? Well, we would expect 4 drops to interact most with 3 drops and 5 drops because of how Hearthstone’s turn system works. And furthermore, we wouldn’t want to give too many points to a four drop because it can kill a bunch of 1 drops (that is expected), and we wouldn’t really expect a four drop to be effective against an 8 drop. The minion efficiency score is the sum of the scores from all the individual simulated interaction between minions.
Here are the results. I’ve plotted each minion as a point in a beeswarm plot with the minion efficiency score on the x-axis. Mouse over each dot to see the associated card.
Where art thou fair yeti?
So where did the Yeti end up? With this model it ended up in 4th place! This is pretty good, it's known to be a fairly efficient minion (among neutrals) and gets a good spot in this model.
In fact every minion that performs better than the Yeti in this model has an accompanying downside and are thus somewhat more situational and/or risky cards to use in your deck.
We can also see that near the Yeti are minions that have the flipped stat-line, i.e. 5 attack and 4 health. Those minions are more aggressive, but also slightly weaker. Depending on what you expect to be facing it can often be difficult deciding between the two.
By adjusting the scores given in the model we can make it favor more aggresive or more defensive minions to fit our needs. If you download the python notebook, feel free to play around with those numbers and see what you get.
At the very top of the pile we see a 4 mana 7-7! Wow, why isn’t everybody playing that? Well as we can see from the card text on the Eerie Statue, it can’t attack unless it's the only minion on the board. This is a pretty big downside as it is fairly easy for an opponent to put a minion on the board before it gets a chance to attack. This makes Eerie statue a very situational card, and one that likely needs to be combined with another card effect to make it useful.
On the other end of the spectrum we see cards like Twilight Drake or Faceless Shambler. Twilight Drake’s health is set to 1 on the card. But it gains health when played depending on how many cards you have in your hand, so its actual health is variable. Faceless Shambler copies the health and attack of a minion that you would already have in play, so its stats are also variable.
This model does not account for these effects at all, and thus can’t properly score these minions with special abilities or card text.
Limitations of the model
It is important to remember that this is just a model of card interactions in the game. It ignores hero powers, weapons, minion effects that occur when they come into play or are killed, or even special abilities like divine shield. I highlighted the Worgen Greaser in the first plot above because it got a good score because of how good it is at trading up, but when I think of all these other factors in the game, it definitely does not deserve the place it was given. This shows a weakness in the model that we may want to go back and adjust for.
Another weakness of the model, and one that I think would be an interesting next step, would be to take into account that not all minions have the same likelihood of being played in the current hearthstone meta-game. It may not matter if the Yeti is good at trading against a particular minion if that minion never actually sees play. For that we would need statistics about actual in game card use (or some proxy for that), which I didn’t have on hand. There are a few tools out there that the community uses to track card decks so it could be something I look at in future. But for now I’ll leave it here.
The full code for this model can be found in this Jupyter Notebook. You could go in there and play with the score assigned to a given interaction to see how that changes the rankings. The main tools used include python and the pandas library. Many thanks go to the HearthJSON and HearthstoneDB projects, from which the data is sourced.
Since I had all the data on hand here are swarm plots for minions for each mana cost from 1-7. As before you can mouse over the dots to see cards, and the minion efficiency score is on the x-axis.