## InfernalShrines.exe has stopped working

Most HotS players have learned a pretty simple rule about Infernal Shrines mechanics: After the first objective, subsequent objectives aren't allowed to have the same punisher type or happen in the same location as the previous. For example: if the first objective had an Arcane Punisher at top shrine, the second objective will have to be Mortar or Frozen, and it will have to be mid or bottom. The map doesn't have to cycle through all three punisher types and locations across three objectives, but it will never repeat a punisher or a location.

I'm here to tell you that you've been lied to, tricked! Not only can the punisher type or shrine location repeat itself, but you can expect it to happen approximately once every ~6746 objectives (past the first). Hopefully, I have shattered your worldview and reshaped the entire way you think about the Infernal Shrines meta with this groundbreaking discovery.

I didn't figure this out myself. Someone added it to the map's Gamepedia page on November 1, 2017; however, I've never seen it reach Reddit, nor could I find an explanation of how it works anywhere. I was curious, so I decided to open CascView and dive in head first. The rest of this post will simply look at the code behind shrine generation. If anyone wants to follow along, I'm looking at **mods/heroesmapmods/battlegroundmods/infernalshrines.stormmod/base.stormdata/LibMSHE.galaxy**, the Galaxy scripting file that contains a lot of the logic behind Infernal Shrines.

## Investigating the RNG

The function **libMSHE_gf_MMISRandomizeNextShrineandShowPreview** at **line 156** is called whenever the game needs to generate a shrine. Here is the relevant portion at **line 167**:

` if ((libMSHE_gv_mMISNumberOfShrinesEvents == 0)) { libMSHE_gv_mMISCurrentShrine = RandomInt(1, libMSHE_gv_mMISNumberofShrinesAllowed); libMSHE_gv_mMISBuffIndex = libMSHE_gf_MMISGetWhichShrine(); } else { while (((libMSHE_gv_mMISLastShrineCounter < 15) && ((libMSHE_gv_mMISCurrentShrine == libMSHE_gv_mMISLastShrine) || (libMSHE_gv_mMISBuffIndex == libMSHE_gv_mMISLastBuff)))) { libMSHE_gv_mMISLastShrineCounter += 1; libMSHE_gv_mMISCurrentShrine = RandomInt(1, libMSHE_gv_mMISNumberofShrinesAllowed); libMSHE_gv_mMISBuffIndex = libMSHE_gf_MMISGetWhichShrine(); } } `

This code has a lot of partially auto-generated variable names, making it ugly to read. It also doesn't include some relevant information, including the following:

**libMSHE_gf_MMISGetWhichShrine()**returns a random number between 1 and 3**libMSHE_gv_mMISLastShrineCounter**is always 0 before reaching this section of the code**libMSHE_gv_mMISCurrentShrine == libMSHE_gv_mMISLastShrine**and**libMSHE_gv_mMISBuffIndex == libMSHE_gv_mMISLastBuff**are always true on the first loop because**libMSHE_gv_mMISCurrentShrine**and**libMSHE_gv_mMISBuffIndex**are never changed outside this function.

For these reasons, I've made a simplified version. More readable variable names, most of it changed to pseudocode, some context added:

`if no shrines have been completed yet, CurrentShrineLocation = a random number between 1 and 3 CurrentPunisherBuff = a random number between 1 and 3 else if at least one shrine has already happened, LoopCounter = 0 CurrentShrineLocation = LastShrineLocation CurrentPunisherBuff = LastPunisherBuff while (LoopCounter < 15 AND (CurrentShrineLocation == LastShrineLocation OR CurrentPunisherBuff == LastPunisherBuff)) LoopCounter += 1 CurrentShrineLocation = a random number between 1 and 3 CurrentPunisherBuff = a random number between 1 and 3 `

As we can see, the first objective will always just be random.

`if no shrines have been completed yet, CurrentShrineLocation = a random number between 1 and 3 CurrentPunisherBuff = a random number between 1 and 3 `

Now let's take a closer look at the while loop:

` while (LoopCounter < 15 AND (CurrentShrineLocation == LastShrineLocation OR CurrentPunisherBuff == LastPunisherBuff)) LoopCounter += 1 CurrentShrineLocation = a random number between 1 and 3 CurrentPunisherBuff = a random number between 1 and 3 `

This part makes it clear just how intentional the design is. If Blizz wanted to ensure that we had a new Punisher and Location no matter what, they would just poll for a random number between 1 and 2 on each of those values, determine the Punisher and Location, and call it a day. Instead, it does the following:

- Generate two numbers between 1 and 3, corresponding to a Punisher and a Location.
- Check if the Punisher and Location are BOTH different from the previous objective.
- If they are both different, success; move on. If not, repeat steps 1 and 2.
- On the 15th attempt, just give up and take whatever Punisher and Location you generated.

The game tries (at most) 15 times to generate a different objective. On attempt 15, it doesn't bother checking to see if it worked, and it just takes the random objective. The 15th attempt might be a new, different objective with a different Punisher and Location, but it also might repeat either the Punisher or the Location.

The chance that a given RNG attempt will succeed at producing a different objective is 2/3 * 2/3, or 4/9. From this, we know that the chance it will *fail* is equal to the complement: 1 – 4/9 = 5/9. We want 15 failures in a row. This is equal to (5/9)^{15}. This gives us 0.00014822191, or 0.014822191%. This is where we get ~0.015% from.

You might be wondering: what are the chances of getting the same **exact** objective twice in a row? Well, the math is pretty easy. Fail the first 14 attempts to get a chance of (5/9)^{14}, then double fail the 15th attempt for a chance of 1/9. Multiply the two together and you get 0.00002964438. This is just under 0.003%, or three in a hundred thousand post-first objectives.

## Final Thoughts

All of this sort of begs the question, why? The design makes it pretty clear that this isn't some bug or oversight; it was clearly designed to have this minuscule chance of failing to create a "different" objective. If they wanted it to never fail, the code would look much more simple. I've seen other games include weird RNG easter eggs (See: Minceraft), but none as obscure as this. It takes several thousand objectives in a row to have a reasonable chance of seeing it. Even if it happens, there's a reasonable chance no one will notice. Even if you notice, it's not particularly funny or Easter Egg-y, it's just strange and you would probably assume it was a bug.

I'm not sure how to end this post. I just find it cool and very, very weird that this mechanic exists.

Source: **Original link**

©Post "Bizarre Infernal Shrines Trivia: Due to RNG, 0.015% of the time, the objective is allowed to have the same Punisher type and Shrine location as the previous objective." for game Heroes of the Storm.

### Top 10 Most Anticipated Video Games of 2020

2020 will have something to satisfy classic and modern gamers alike. To be eligible for the list, the game must be confirmed for 2020, or there should be good reason to expect its release in that year. Therefore, upcoming games with a mere announcement and no discernible release date will not be included.

### Top 15 NEW Games of 2020 [FIRST HALF]

2020 has a ton to look forward to...in the video gaming world. Here are fifteen games we're looking forward to in the first half of 2020.