Space-G

The Brazillian Menace™

Discord username: spaceg

Profile picture drawn by matsukun at Twitter


Website League
lilypad.frogge.cafe/@spaceg

rgmechex
@rgmechex

The last video on the main channel looked into the roulette/slot machine minigame in Super Mario Bros. 3. It has a fuzzing mechanic that prevents you from skillfully winning the game each time (despite how oh so many comments say they have a method for winning the game). The last segment of the roulette turns out to be 100% random with approximately a 25% chance of each of the four icons showing up.

Thumbnail for the video SMB3 Roulette & Card Matching Games ExplainedIf you haven't seen the video yet, you should watch it since some of this might not make sense.

This article will go into more detail about the exact probabilities of each icon appearing for each of the three segments, as well as showing what the optimal timings are to try to get that sweet 5up every time.


The video briefly mentions three of the six states that the roulette segments can be in. Let's look at all six of them in a bit more detail.

State 0: Spinning

This is the most basic state. The speed of each segment is added to its position causing them to move every frame. The main portion of the code for this state is actually shared among the first five states, since the segments are always updating their position until they come to a complete stop.

Each segment's speed is defined as a signed 4.4 fixed point value in pixels per second. Here are the initial speed values for each of the three segments:

SegmentSpeed (hex)Speed (px/fr)
1$707
2$90-7
3$7F7.9375

The first two segments always have positions aligned to the pixel grid, but the third segment actually uses subpixels. Since it moves at 7 and 15/16 pixels per frame, it realistically moves 8 pixels for 15 frames, and then only 7 pixels for one frame, before repeating this pattern. This averages out to 7.9375 pixels per frame.


State 1: Rigged Delay

This is what the video was all about. When a button is pressed to stop a segment, the RNG is used to determine a random number of frames the game will delay this segment until it actually starts to slow down. This makes the game unpredictable and ultimately impossible to be consistent at.

Here is a recap of the possible amounts of delay for each segment:

SegmentBase Delay (fr)Maximum Rig Delay (fr)Possible Delay Range (fr)
1321532-47
2323132-63
3646364-127

The entire length of the roulette wheel is 512 pixels, and it is split into 4 quadrants, one icon on each. So each icon is 128 pixels wide. Using some math, we can convert the rigged delay ranges from in terms of frames to in terms of portions of icons. Remember that since the third segment is faster, it has a different conversion rate:

SegmentSpeed (px/fr)Size (px/icon)Speed (icon/fr)Delay Range (fr)Delay Range (icon)Maximum Rig Delay (icon)
171280.054732-471.75-2.2570.820
2-7128-0.054732-631.75-3.4451.695
37.93751280.062064-1273.969-7.8753.907

I understand that this is kind of a weird metric so let me clarify. The right-most column here essentially represents the worst possible "fuzz" amount that can be applied to a button press on that segment. So for example, if you press a button to stop the first segment, it will try to stop at some point X on the roulette. With smallest fuzzing number grabbed from the RNG, it will stop right at this point. But with the largest fuzzing number, it will stop 82% of one icon later than it would have with the smallest number. So if that point X were, say, the trailing end of the star icon, this amount of delay would cause you to land on the mushroom icon instead. However, if that point X were the very very start of the star icon, this amount of delay would let you land on the very very end of the star icon. This is because the fuzzing amount is less than a full icon's width.

This implies that there is an ideal position of the first roulette segment that can guarantee you a star every time. And indeed there is! You even have a 3.285 frame window to hit it (there are 23 roulette positions that can guarantee a star, and the segment moves at 7 pixels per frame).

The first segment of the roulette highlighted with the star just left of centerThe best time to stop this segment is when the star just passes the center of the screen.

The second segment has a fuzzing amount of about 170% the width of one icon. Since this is bigger than one icon, this means that there is no position that will guarantee a star. However, there is a window that will give you the best chances for a star. This one has a 13.286 frame window (93 positions at 7 pixels per frame), but you will only have a 19/32 or 18/32 (59.375% or 56.25%) chance of getting the star depending on the exact frame.

The second segment of the roulette highlighted with the star just left of centerThe best time to stop this segment is right before the star lines up in the center of the screen.

The third segment has a fuzzing amount of about 390% of the width of one icon. This is about 97.7% of the width of the entire roulette. This essentially means that you have almost an equal chance of landing on one of the four icons no matter when you press the button. However, it's not exactly 100%, so there is technically a best window to try to get the star. However, it will only ensure you get a 17/64 or 16/64 (26.6% or 25%) chance at the star instead of a 15/64 (23.4%) chance.

The third segment of the roulette highlighted with the star near the left of the screenThe best time to stop this segment is right when the star is leaving the left side of the screen. It won't make that big of a difference though.

Here are some diagrams that show exactly which icon will appear when you press the button when the segment is at a given position and given the amount of rigged delay frames dictated by the RNG. Each horizontal slice of this chart represents one position of the roulette, and you can create a pie chart out of the colors in the slice to determine the likelihood of each icon appearing.

Diagram showing roulette position versus rig delay amount; the area is split into three regions which correspond to getting a mushroom, flower, and star

For example, here is the diagram for the first segment. The highlighted area is the region where the horizontal slices are completely yellow--these are guaranteed stars. The very top row of the chart represents the segment's position of 0. From that, you can determine that if the RNG gives you 0-4 frames of rig delay, you will get a star, and 5-15 will get you a mushroom.

Diagram showing roulette position versus rig delay amount; the area is split into three regions which correspond to getting a mushroom, flower, and star

Here is the diagram for the second segment. It is twice as wide since you can get twice as many frames of rig delay, and the pattern goes down instead of up since the segment moves the opposite direction. Note that there is no horizontal slice that is entirely one color, so you can not ever guarantee a certain icon.

Diagram showing roulette position versus rig delay amount; the area is split into three regions which correspond to getting a mushroom, flower, and star

And finally here is the third segment. Twice as wide again--since it is so wide, you can see that each horizontal slice essentially makes each icon a 25% chance. The highlighted area is the bad zone where the star is least likely.

Here is a fun animated version of these diagrams that shows the pie charts in real-time if you were to stop the segment on that frame:

The spinning roulette with three pie charts updating to reflect the chances of each icon appearing at that particular frameThe bottom segment spins fast enough (and because of subpixels) that most of the time you don't even have an opportunity to get that bonus 17/64 chance for the star.


State 2: Slowing Down

In this state, the magnitude of the segment's speed is reduced by $0.2 pixels per frame per frame (0.125 pixels per frame per frame). Once the magnitude of the speed is less than 4 pixels per frame, it moves to the next state. Simple enough.


State 3: Lining Up

This state is responsible for making sure that the icon on the segment lines up in the middle of the screen. The segment will continue at its ~4 pixels per frame speed until the icon is close enough to the middle of the screen. Since it's only moving at less than 4 pixels per frame, it just checks that the icon is within 4 pixels of the center of the screen. This ensures that it will always stop at the next available icon.

Once it's near the middle, the bloop sound effect is played, a counter is started at 18 for the next state, and the segment is forced to line up exactly in the middle. (It only shifts by a maximum of 3 pixels so you don't really notice it jerk over if it needs to.)


State 4: Shaking

All this state does is make the segment shake a bit before it stops. It shakes for 18 frames total (set by the previous state). That counter is decremented once per frame until it reaches zero, at which the segment moves into the next state.

The game sets the speed of the segment to plus or minus 1 pixel per frame depending on bit 2 of this counter. This makes the segment specifically move right for 2 frames, left for 4, right for 4, left for 4, and right for 4 more frames.


State 5: Stopped

This is the only state where the segment doesn't update its position from its speed property. This is also the state that triggers the code that actually checks for a match and gives lives if necessary (it's hardcoded specifically for the final segment only).


While I did create a script to help emulate exactly how the roulette game works, the diagrams above were made by brute forcing every possible frame you can press a button to stop the roulette segments. This was done for two reasons: first, as a sanity check for my own research (always a good thing); second, to prove to myself and everyone else that keeps telling me there's a way to always get a star every time. No there's not!!

A line graph showing the positions of the three segments over timeHere's a chart from my script that shows how the positions of the three segments change over time.


You can support Retro Game Mechanics Explained on Patreon here! Any and all support is greatly appreciated!


You must log in to comment.

in reply to @rgmechex's post: