Shortly after the release of Avengers: Infinity War, the site DidThanosKill.me appeared, and many of my friends visited it and shared their results. There were two possible outcomes:
- You were spared by Thanos.
- You were slain by Thanos, for the good of the Universe.
If you tried to reload the page to get a different result, you quickly learned that you can’t cheat fate. Once you got a result from DidThanosKill.me, it stayed that way, no matter how many times you reloaded the page.
If you’re new to programming, or if you’ve hit that point where you can follow a programming tutorial but are having trouble taking an idea and turning it into an application, this article is part of an ongoing series that will help you.
Nerd interlude (or: a little background for people who didn’t read comics in the ’90s)
The eradication of half the life in the universe happened (both in the 1991 comic book The Infinity Gauntlet and the movie, which borrows bits and pieces from the comic book) when Thanos gathered the Infinity Gems/Stones (in the comics, they’re Gems, and they were originally called the Soul Gems; in the movies, they’re Stones)…
…into the Infinity Gauntlet, giving him near-unlimited power. In the comics, Thanos did this to impress and win the love of Death — the cosmic entity, personification of death, and Thanos’ dream woman:
The “to challenge humans is to court death” post-credits scene from the first Avengers movie gave the non-comic-book-reading audience its first glimpse of Thanos and hinted at the possibility that they might go with the same storyline…
…but instead, they went with a more mundane, Malthusian motivation for Thanos: bringing balance to the universe, and population control. It’s a pity, because the Marvel Cinematic Universe had already introduced a great death goddess character who would’ve worked wonderfully with the “Thanos is in love with Death” idea:
How DidThanosKill.me works: The high-level version
In both the movies and the comics, when Thanos finally gets all the gems/stones in the Gauntlet, he uses its power to kill off half the life in the universe by random selection. The word random should be your hint that a random number generator is involved.
The other thing that DidThanosKill.me does is remember whether or not Thanos killed you. When a web app remembers something about a particular visitor without requiring that visitor to log in first, that’s your hint that it’s probably making use of a cookie.
How DidThanosKill.me works: Looking at the actual code
Let’s take a look at DidThanosKill.me’s source. This is the complete source for that page, which you can see when you use your browser’s View Source functionality on DidThanosKill.me:
<!DOCTYPE html> <html> <head> <title>Did Thanos Kill You?</title> <meta name="description" content="Did Thanos kill you?"> <meta name="keywords" content="did,Thanos,kill,me,you,avengers,infinity,war,half,fifty,50,percent,snap"> <meta name="author" content="Tristan Bellman-Greenwood"> <script> function getCookie(cname) { var name = cname + "="; var decodedCookie = decodeURIComponent(document.cookie); var ca = decodedCookie.split(';'); for(var i = 0; i <ca.length; i++) { var c = ca[i]; while (c.charAt(0) == ' ') { c = c.substring(1); } if (c.indexOf(name) == 0) { return c.substring(name.length, c.length); } } return ""; } function onLoad() { var displayElement = document.getElementById("display"); var randomNumber = getCookie("thanosNumber"); if (!randomNumber) { randomNumber = Math.random(); document.cookie = "thanosNumber=" + randomNumber + "; expires=Fri, 3 May 2019 00:00:00 UTC"; } else { randomNumber = Number(randomNumber); } if (randomNumber < 0.5) { displayElement.textContent = "You were slain by Thanos, for the good of the Universe."; } else { displayElement.textContent = "You were spared by Thanos."; } } function clearCookie() { document.cookie = "thanosNumber=; expires=Thu, 01 Jan 1970 00:00:00 UTC"; location.reload(); } </script> </head> <body onload="onLoad()"> <div style="width: 100%; height: 100%;"> <span id="display" style="position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); font-family: sans-serif; font-size: 4em; text-align: center;"></span> <!-- <button onclick="clearCookie()">Clear Cookie</button> --> </div> </body> </html>
Making the code run as soon as the page is done loading
On line 50, you’ll find the body
tag:
<body onload="onLoad()">
This is an often-used technique to make something happen when the page loads:
- The
onload
event occurs when the object it belongs to has fully loaded. - In the case of the
body
tag, theonload
event happens when the body of the web page has fully loaded, which means that it has loaded all content, including images, scripts, CSS, and so on. - With this particular
body
tag, once the web page has fully loaded, it executes theonLoad()
method.
The method where everything happens
The onLoad()
method lives in the script
tag (it starts at line 25) and looks like the code below, with one key exception: I’ve added a couple of numbers at the end of key lines, which correspond to the items below the code.
function onLoad() { var displayElement = document.getElementById("display"); // 1 var randomNumber = getCookie("thanosNumber"); // 2 if (!randomNumber) { // 3 randomNumber = Math.random(); document.cookie = "thanosNumber=" + randomNumber + "; expires=Fri, 3 May 2019 00:00:00 UTC"; } else { // 4 randomNumber = Number(randomNumber); } if (randomNumber < 0.5) { // 5 displayElement.textContent = "You were slain by Thanos, for the good of the Universe."; } else { displayElement.textContent = "You were spared by Thanos."; } }
1. It gets the HTML element that will display the “You were slain” or “You were spared” message.
It does this by getting the element whose id
is display
and assigns it to the variable displayElement
.
If you look at line 52 of the source, you’ll see that this element is a span
that is:
- Set in the center of the screen (as determined by
position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);
in thestyle
attribute) - Has a large font size (as determined by
font-family: sans-serif; font-size: 4em;
in thestyle
attribute) - Is center-aligned (as determined by
text-align: center;
in thestyle
attribute)
The span
will eventually contain the text that will display either “You were slain by Thanos, for the good of the Universe”, or “You were spared by Thanos.”
2. It checks to see if the user’s fate was already determined and memorized during a previous visit.
This is done by calling a method named getCookie()
, which tries to get the value of the cookie with the given key. In this case, the key is thanosNumber
. A cookie with the key thanosNumber
would exist on the user’s system only if the user had visited the site before and didn’t clear the browser’s cookies since then.
- If user’s system contains a cookie with the key
thanosNumber
,getCookie("thanosNumber")
returns the value associated with that key, and that value gets put into the variablerandomNumber
. - If the user has never visited DidThanosKill.me before (or cleared their cookies since their last visit), the user’s system not contain a cookie with the key
thanosNumber
. The call togetCookie("thanosNumber")
would result in anull
value, which would then be put into the variablerandomNumber
.
At this point, randomNumber
contains either null
or a value.
3. If the user’s fate hasn’t already been determined and memorized, it determines and memorizes the user’s fate.
If randomNumber
contains null
, the following happens:
- A random number between 0 and up to (but not including) 1 is generated and stored in
randomNumber
. This number represents the user’s fate. - The value in
randomNumber
is saved to the user’s system in a cookie with the keythanosNumber
.
4. If the user’s fate has already been determined and memorized, it recalls the user’s fate.
The value in randomNumber
is converted to its numerical equivalent.
5. It displays the user’s fate.
At this point, as a result of either step 3 or step 4, randomNumber
is guaranteed to contain a number between 0 and up to (but not including) 1.
- If the value in
randomNumber
is less than 0.5, the user was slain by Thanos, and this fate is displayed onscreen. - If the value in
randomNumber
is greater than 0.5, the user was spared by Thanos, and this fate is displayed onscreen.
And thus half the universe is spared, and half the universe dies.
An exercise for the reader
There are still two bits of the code that I haven’t yet explained, and they’re the ones that read and write the cookie data. The first is the getCookie()
function…
var name = cname + "="; var decodedCookie = decodeURIComponent(document.cookie); var ca = decodedCookie.split(';'); for(var i = 0; i <ca.length; i++) { var c = ca[i]; while (c.charAt(0) == ' ') { c = c.substring(1); } if (c.indexOf(name) == 0) { return c.substring(name.length, c.length); } } return ""; }
…and the second is clearCookie()
:
function clearCookie() { document.cookie = "thanosNumber=; expires=Thu, 01 Jan 1970 00:00:00 UTC"; location.reload(); }
See if you can figure them out. I’ll explain how they work in a future article.