How Long Should You Squeeze the Egg in Egg Squeeze?
Egg Squeeze is a biological intuition test where you squeeze eggs for as long as you can without breaking them. The longer you squeeze the egg, the more points you get. If you break the egg, you lose points. In the game, you are supposed to use your “psychokinetic intuition” to sense when the egg will break. In reality, there is no audio or visual indicator for when or how fast the egg will break. All you can do is guess.
This game has a lot of interacting systems that we don’t fully understand yet. For example, there is a simulated war between green eggs and red eggs going on in the background, and the community hasn’t figured out what it actually does. We suspect that the outcome of battles in the war influences the stock price of eggs. This is very important because stock price acts as a multiplier for how many points you score. On the other hand, some people suspect that the war has no effect on the game because much like in real life, war is pointless.
I wanted to win the speedrun world record. I made a statistical model of the game, used that model to simulate the game with different strategies, and learned the best strategy to win the game.
How Long Until Eggs Break?
I squeezed over 500 eggs to get a idea of what the distribution looks like.
We can infer that the time it takes to break an egg is a uniformly distributed random number between 3 and 10 seconds. The probability that your egg will break by time can be given by the following equation.
I truly thought that the egg break times were not truly random. It felt like the break time was generated using a stochastic process such as a random walk, weiner process, etc. For example, you would get a few high numbers in a row followed by a few low numbers in a row.
breaking_times.diff().var().item()
8.075461129171831
The variance of the difference between consecutive values is in line with what we would expect from randomly generated numbers.
= np.random.uniform(3, 10, 500 * 1000).reshape(500, 1000)
random_samples = np.diff(random_samples, axis=1).var(axis=1)
variances f'mean = {variances.mean().item()}, std = {variances.std().item()}'
'mean = 8.166820712695573, std = 0.3526209259472838'
This, in addition to the fact that the distribution is uniform and not normal, is enough evidence for me to say it’s unlikely that the break times are generated from a stochastic process.
Modeling Synergy Reward and Loss
“Synergy” is the quantification of your connection with eggs. Our goal is to get as much synergy as possible.
When you break an egg, you lose exactly of your current synergy.
When you squeeze the egg but you don’t break it, you gain synergy. We don’t know how the reward is calculated. I recorded about 400 data points to get an idea.
The First Squeeze
This scatter plot shows how much synergy I gained when I had 0 synergy. It clearly shows two sets of lines - the top and bottom lines. The points in the bottom lines are from the true first squeeze. The points in the top lines are from when I broke the first egg and squeezed again. Clearly, there is a separate function for the true first squeeze.
These two functions are the same, but the bottom one is scaled down by , which means that your very first squeeze is divided by 3.
Beyond the First Squeeze
The following scatter plots show how much synergy I gained at various intervals.
The pattern is obvious, but it’s seems like it’s going to be harder to reverse engineer the reward function than I initially anticipated. If how much synergy you gained was a strictly-increasing function of percentage and current synergy, then you would expect to see distinct “bands” in the plot, but you can clearly see that the colors are mixed into each other or are really unexpected. I suspect that either there is a random (error) factor or that there is some mechanic in the game that I’m not accounting for.
The data has a lot of bias. Most of the data is clustered at the low synergy end. I split the data up into multiple sections and fit different functions to them using regression, to mild success. I didn’t put too much thought into figuring out the form of the underlying function because I don’t need that good of a fit right now.
Tail Behavior
The more synergy you have, the more synergy you will gain per squeeze. After a certain point, it seems to stop growing. The amount of points you gain per squeeze is about the same at 30 million up to 900 million synergy. We can approximate the final relationship with the following equation:
After a certain point, trying to get synergy normally is futile. At one billion synergy, if you accidentally break the egg, it will take 222 squeezes to get back to 1 billion synergy. It will take 2,666 99% squeezes (each giving you 1.5 million synergy, and taking you around 4 hours) to match the amount of synergy of a single 4x investment deal.
Final Reward Function
We can finally create an approximate model of the reward function that takes , the percentage squeezed, and , the current synergy as parameters.
def r(p, c):
if p < .15:
return 1
elif c <= 3e7:
return reward_model(p, c)
else:
return 3.213e4 * e ** (3.742*p)
Expected Reward Per Squeeze
Assuming that the egg hasn’t broken yet, we can calculate the expected reward you will get if you choose to stop squeezing the egg at time when you currently have synergy.
The first term represents how much synergy you will lose if the egg broke before . The second term represents how much energy you will win on average if the egg doesn’t break before .
Note that the x axis is logarithmic. We can clearly see how steeply the expected reward goes down as the current synergy goes up. This is because the loss of losing of your synergy when breaking an egg quickly outgrows how much synergy you might gain per squeeze.
From 1-400, you have the highest expected reward at 3 seconds. From around 500-1000, the best time goes up to 4.8 seconds and then goes back down to 3 seconds before 5000.
How do multipliers affect the expected reward? If we have a rainbow egg, we can multiply the reward by 3.
We can see that you’re probably going to lose synergy around the 1 million mark and it’s going to be very hard to get to 10 million synergy which is required to beat the game.
Simulating Egg Squeeze to Find the Best Strategy
With what we’ve found, we can build a simulation of the game and stochastically find which strategies perform well. I don’t know what the real reward function is, so I feel I can only solve this numerically. The only cost unit I’m currently tracking is real-life time, so these statistics can tell you which strategies work well for speedruns.
= (3, 10)
egg_break_time_range
def simulate_game(strategy_func, target_synergy: int, iteration_limit:int=20000) -> float:
= egg_break_time_range
t_min, t_max = 0
t = 0
current_synergy for _ in range(iteration_limit):
= strategy_func(current_synergy)
t_s = random.random() * (t_max - t_min) + t_min
t_break if t_s >= t_break:
-= current_synergy / 3
current_synergy += t_break
t else:
+= max(r(t_s / t_break, current_synergy), 0)
current_synergy += t_s
t if current_synergy >= target_synergy:
return t
+= 1 # time it takes to get past post-squeeze summary
t return -1
def coward_strategy(_) -> float:
return 3
find_strategy_statistics(coward_strategy)
target synergy | mean time | std | % beat WR pace | |
---|---|---|---|---|
2 | 30000 | 54.83 | 13.46 | 36.14% |
1 | 1000000 | 198.99 | 43.21 | 1.96% |
0 | 9999999 | 386.68 | 47.09 | 1.72% |
def almost_coward_strategy(_) -> float:
return 3.5
find_strategy_statistics(almost_coward_strategy)
target synergy | mean time | std | % beat WR pace | |
---|---|---|---|---|
2 | 30000 | 77.13 | 21.56 | 7.92% |
1 | 1000000 | 282.93 | 85.87 | 0.26% |
0 | 9999999 | 770.19 | 270.36 | 0.00% |
def average_squeezer_strategy(_) -> float:
return 3 + 7 / 2
find_strategy_statistics(average_squeezer_strategy)
target synergy | mean time | std | % beat WR pace | |
---|---|---|---|---|
2 | 30000 | 379.63 | 290.33 | 0.08% |
1 | 1000000 | 5173.41 | 4794.05 | 0.00% |
0 | 9999999 | nan | nan | nan% |
def random_strategy(_) -> float:
return random.random() * 7 + 3
find_strategy_statistics(random_strategy)
target synergy | mean time | std | % beat WR pace | |
---|---|---|---|---|
2 | 30000 | 479.21 | 377.60 | 0.14% |
1 | 1000000 | 33078.53 | 28114.29 | 3.11% |
0 | 9999999 | nan | nan | nan% |
When trying to reach 10 million using the random and average squeezer strategy, none of the simulations reach it before the timeout (20,000 squeezes).
def expected_strategy(current_synergy) -> float:
"""
This strategy chooses the time you have the highest expected reward
as show in the previous section
"""
if 500 <= current_synergy and current_synergy <= 1200:
return 3.5
else:
return 3
find_strategy_statistics(expected_strategy)
target synergy | mean time | std | % beat WR pace | |
---|---|---|---|---|
2 | 30000 | 55.46 | 13.60 | 37.30% |
1 | 1000000 | 200.05 | 42.78 | 2.02% |
0 | 9999999 | 387.00 | 46.44 | 1.38% |
It looks like the coward strategy really is the best strategy on average. It assumes that the player can squeeze the egg for exactly 3 seconds each time. What happens if we add some human error? I modeled the error as a normal distribution where
def human_coward_strategy(_) -> float:
return 3 + random.normalvariate(0, .5 / 3)
find_strategy_statistics(human_coward_strategy)
target synergy | mean time | std | % beat WR pace | |
---|---|---|---|---|
2 | 30000 | 56.28 | 14.64 | 34.36% |
1 | 1000000 | 215.85 | 50.02 | 1.18% |
0 | 9999999 | 424.78 | 61.22 | 0.50% |
It performed only slightly worse.
It looks like the best strategy is to squeeze for exactly 3 seconds.
Whenever I’m doing a speedrun, I’m so tempted to squeeze longer so I can have better odds at getting higher percentiles. Does this really make sense?
= (5.5, 10)
egg_break_time_range
lambda _: 5.5) find_strategy_statistics(
target synergy | mean time | std | % beat WR pace | |
---|---|---|---|---|
2 | 30000 | 91.58 | 29.77 | 2.50% |
1 | 1000000 | 192.09 | 38.02 | 1.48% |
0 | 9999999 | 384.83 | 40.37 | 0.66% |
= (6.5, 10)
egg_break_time_range
lambda _: 6.5) find_strategy_statistics(
target synergy | mean time | std | % beat WR pace | |
---|---|---|---|---|
2 | 30000 | 74.60 | 19.34 | 4.26% |
1 | 1000000 | 158.84 | 24.07 | 10.12% |
0 | 9999999 | 344.42 | 27.39 | 4.66% |
= (7.5, 10)
egg_break_time_range
lambda _: 7.5) find_strategy_statistics(
target synergy | mean time | std | % beat WR pace | |
---|---|---|---|---|
2 | 30000 | 60.65 | 10.78 | 4.42% |
1 | 1000000 | 133.14 | 13.16 | 45.44% |
0 | 9999999 | 309.27 | 15.66 | 30.56% |
Squeezing for exactly 3 seconds might be the best strategy, but on day 2 and 3 you are certainly rewarded for going for high squeeze times assuming you’re lucky enough to never break your egg.
Egg Co. Investment Offer Strategies
Occassionally, you get a phone call with this dilemma:
- Multiply your current synergy by a factor of
- But you must squeeze the egg at least % of its maximum time on your next squeeze or else you lose all your synergy
For example, 4x your current synergy but you must get 50% on your next squeeze.
Most people will always refuse the offer because they don’t want to lose their synergy, but He who is not courageous will achieve nothing in life.
The probability that you win the deal at time can be given by the following equation.
You can imagine a “zone” from to which are break times where can possibly win the deal. For example, if and , then you can win the deal if the true break time lies between 3 and 6 seconds. Your probability of winning is the ratio of this zone to the total 3-10 second span of all possible break times.
The best time to stop squeezing is when the probability of winning the deal is at its highest — when the “zone” is as large as possible.
Increasing Our Odds with Modules
As you earn points, you can unlock modules. At a first glance they seem useless but they are actually very powerful. The two modules we care about the most are:
- The Buddy Module, which tells you whether the number of seconds is even, odd, or 9.
- The Egg Meter module, which tells us the value (minus 1) of the tenths digit of when the egg will break. For example, if the egg breaks at 6.4 seconds, the Egg Meter will say “3”.
You typically get the Egg Meter modile first, and the Buddy Module late in the game. The Egg Meter module by itself is not very useful.
By using these two modules together, we can limit the possible times that the egg can break to one or three possibilities. For example, if Buddy tells us the seconds are even and the meter tells us the tenths digit is 3, then we know the egg will break at 4.3, 6.3, or 8.3 seconds. If Buddy instead told us the egg will break at 9 seconds, then we know exactly when the egg will break — 9.3 seconds.
We can redefine our probability of breaking the egg as follows:
Where represents the tenths decimal .
New Squeeze Strategy With Modules
We can update our expected reward function to reflect the new probabilities.
def E_with_modules(t_s, c, possible_times):
= 0
output = 1 / len(possible_times)
f for t in possible_times:
if t <= t_s:
-= (c / 3) * f
output else:
+= r(t_s / t, c) * f
output return output
def E_odd(t_s, c, d):
return E_with_modules(t_s, c, [3+d, 5+d, 7+d])
def E_even(t_s, c, d):
return E_with_modules(t_s, c, [4+d, 6+d, 8+d])
def E_9(t_s, c, d):
return E_with_modules(t_s, c, [9+d])
Taking Investments When Using Modules
When you have access to the Egg Meter module, in the best case it increases your chance of winning to at least (assuming you took a deal where you need to get at least 90% on your next squeeze.).
When you have access to the Egg Meter and Buddy modules, you have exactly a or chance of winning the deal. Since the modules tell limit the possibilities to three, you can almost guarantee at least a chance by choosing any of them. If the percentile requirement is lentient enough, you can time it just right to be “in range” forthe latter two options (5.X and 7.X, or 6.X and 8.X) to get a chance of winning the deal.
This table shows the maximum percentile allowed to have a chance of winning the deal.
d | odd | odd, >.5s window | even | even, >.5s window | |
---|---|---|---|---|---|
0 | 0.0 | 71% | 64% | 75% | 68% |
1 | 0.1 | 71% | 64% | 75% | 69% |
2 | 0.2 | 72% | 65% | 75% | 69% |
3 | 0.3 | 72% | 65% | 75% | 69% |
4 | 0.4 | 72% | 66% | 76% | 70% |
5 | 0.5 | 73% | 66% | 76% | 70% |
6 | 0.6 | 73% | 67% | 76% | 70% |
7 | 0.7 | 74% | 67% | 77% | 71% |
8 | 0.8 | 74% | 67% | 77% | 71% |
9 | 0.9 | 74% | 68% | 77% | 71% |
Whether or not you can get a chance of winning is entirely dependent on your skill. You need to stop squeezing as close to 5.X or 6.X as possbible in order to get both possibilities in range.
You should always go for the middle option. If you under or overshoot it, you will have a chance of winning the deal which is the same as if you went for the first or second option.
The World Record Run
Conclusion
Egg Tuah