About
An arcane mystery as old as time itself: What is the best Minecraft mob?
MobMash is a website that lets visitors vote on which mob from the video game Minecraft they like best by choosing one of the two mobs presented on the homepage. Based on this relative decision, an algorithm then calculates an absolute rating for the mobs. If you are interested in the technical implementation, skip down to the Implementation section, or take a look at the source code on GitHub.
The Story
Back when I was in school, I watched The Social Network movie. I was fascinates by the scene in which Zuckerberg implemented Facemash in an eventing. So, I was kind of curious if I could manage that too - I couldn't. I took me 3 evenings to implement even a rather basic version. (Writing this now, I also found out that it took Zuckerberg a week - not just an evening. Welp.) Instead of students, my version used pictures of my professors, that I scraped from my school's website - which, in retrospect, was morally a bit problematic.
Recently, I found the old source code again, and I was thinking: Maybe I can rewrite it. Let's not use humans this time. Instead, let's use something nerdy: Minecraft mobs. And while we are at it, let's also do it properly - the previous version really was quite bad from a technical perspective.
Implementation
The basic idea is to give the users a choice between mobs. The better one is selected, and its internal rating increases. The algorithm used is the Elo rating system. I won't go into details here, but the basic idea is the following: It works by assigning each candidate a number and calculating the winning probabilities for each match. This winning probability then determines how many points are gained/lost by each candidate.
We can also use this rating to calculate the ideal pairing. Mobs that have a similar rating might be more engaging to compare than mobs where it's obvious which one is better.
The challenge here is twofold: First, we need to be able to asynchronously calculate and write the ratings to the database. This could theoretically be solved by utilizing transactions. The other problem is that I want to be able to delete entries from the database in case I detect spam or "cheating". So, we need a list of all changes, so we can undo them if necessary - which would also mean we need to recompute all ratings after the deleted ones, as they linearly depend on each other.
The way I chose to solve those problems was by doing the calculations in on-the-fly in the database. The
only thing we have to store are the match-ups, including the winner and the date for sorting. The rating
calculation is then done by starting from a base rating for each mob (1500 in this case) and applying each
match to the ratings in sequence using a recursive query. (As a side note: Initially, I tried to keep each
rating in its own row. However, I was unable to make it work. I'm not sure if that's a limitation of
PostgreSQL or if I'm just not smart enough.
Either way, the current solution uses jsonb
objects for the rating state - which also turned
out to be much faster than having each rating as its own object.)
This approach works quite well and can handle a few thousand votes with no issues. However, since we need to iterate over all matches every time we want to calculate the next pairing, it doesn't scale well beyond that. My solution for this was to introduce a caching table that contains a recent snapshot of the ratings. The recursive calculation then seeds itself with the cache instead of starting from scratch. This cache can be generated regularly (maybe once a day) to keep the responses snappy.
The flip side of using this cache is, of course, that in case I need to delete some matches, I also have to delete the corresponding cache entries. It's not a huge deal, but certainly something to be aware of.
If you would like to learn more, I posted an article about the details over on my blog. You can also check out the source code on GitHub. Pull Requests are welcome!
Statistics
There are currently 82 mobs in the system. The top-ranked mob is "Cat", with a rating of 2,243. Last place is "Phantom" with a rating of 1,341.
"Cat" has fought the most matches: 1,271, out of which it won 1,241. Which also makes it the mob with the most wins.
Until now, there have been 4,031 votes.
Over the past 6 months, there have been 79 unique voters. On average, each one voted 51.0 times, with 270 (You people are mad!) as the maximum.
So far, none have voted for all 6,724 pairings yet.
Contact
If you want to contact me regarding this website, please use the following email address:
Credits & Tech Stack
Minecraft-Related Content
Minecraft content and materials are trademarks and copyrights of Mojang Studios.
Fonts, Icons, Emoji
- Minecraft Font by JDGraphics (Public Domain)
- Font Awesome v4.7.0 (OFL-1.1 & MIT)
- Twemoji (CC BY 4.0 & MIT)
Frontend Frameworks
Backend Technologies
Special Thanks
I'd like to thank the Minecraft Wiki for letting me use their API to automatically update the mobs in the vote. The pictures for the mobs are also provided by them.
Also, I'm awful at design. So, a big thanks goes to the web designer who helped me! (They would like to stay anonymous. Apparently, the design is not good enough. )