Skip to content

Instantly share code, notes, and snippets.

@Nikolaj-K
Last active March 10, 2024 13:03
Show Gist options
  • Save Nikolaj-K/b9015c76e72f58020b8051c2f8f8f6ab to your computer and use it in GitHub Desktop.
Save Nikolaj-K/b9015c76e72f58020b8051c2f8f8f6ab to your computer and use it in GitHub Desktop.
Computing the best ratio of lotus to recall among lotus-recall-only decks
"""
Script discussed in
https://youtu.be/s5ud06udqT0
"""
import random
NUM_GAME_SIMS = 10 ** 7
Lotus = 'Lotus'
Recall = 'Recall'
DECK_SIZE = 60
NUM_CARDS_STARTING_HAND = 7
REQUIRED_RECALLS_TO_WIN = 18 # roof of (DECK_SIZE - NUM_CARDS_STARTING_HAND) / 3
class Game:
def __init__(self, num_of_recalls):
self.num_of_recalls = num_of_recalls
self.num_of_lotuses = DECK_SIZE - num_of_recalls
def draw(self, num_cards):
for _ in range(num_cards):
if self.deck[0] == Recall:
self.recalls_in_hand += 1
else:
self.mana_pool += 3
self.deck = self.deck[1:]
def play_recall(self):
self.mana_pool -= 1
self.recalls_in_hand -= 1
self.draw(3)
def run(self):
self.deck = self.num_of_recalls * [Recall] + self.num_of_lotuses * [Lotus]
self.recalls_in_hand = 0
self.mana_pool = 0
# Get starting hand
for num_starting_hand in range(NUM_CARDS_STARTING_HAND + 1)[::-1]:
if num_starting_hand == 1:
return 1 # Too many mulligans, first turn kill not possibly anymore
random.shuffle(self.deck)
potential_hand = self.deck[:num_starting_hand]
if Lotus in potential_hand and Recall in potential_hand:
self.draw(num_starting_hand)
break # At least one recall and one lotus => good to go
while len(self.deck) >= 3:
if self.recalls_in_hand == 0 or self.mana_pool == 0:
return 1 # Out of recalls or out of mana
self.play_recall()
if self.recalls_in_hand >= REQUIRED_RECALLS_TO_WIN and self.mana_pool >= REQUIRED_RECALLS_TO_WIN:
return 0 # Win
return 1 # Milled yourself to death (TODO: This assumes 53 cards at start and not more (from potential mulligan))
for num_recalls in (36, 37, 38, 39, 40):
game = Game(num_recalls)
fails = 0
for _ in range(NUM_GAME_SIMS):
fails += game.run()
percent = "{:3.3f}".format(100 * fails / NUM_GAME_SIMS)
print(f"Simulated {NUM_GAME_SIMS} games starting with {num_recalls} recalls. Fails: {fails}, or {percent} %")
exit("Done.")
"""
num_recalls = 10000
Simulated 10000 games starting with 23 recalls. Fails: 10000, or 100.000 %
Simulated 10000 games starting with 24 recalls. Fails: 10000, or 100.000 %
Simulated 10000 games starting with 25 recalls. Fails: 10000, or 100.000 %
Simulated 10000 games starting with 26 recalls. Fails: 10000, or 100.000 %
Simulated 10000 games starting with 27 recalls. Fails: 10000, or 100.000 %
Simulated 10000 games starting with 28 recalls. Fails: 10000, or 100.000 %
Simulated 10000 games starting with 29 recalls. Fails: 10000, or 100.000 %
Simulated 10000 games starting with 30 recalls. Fails: 10000, or 100.000 %
Simulated 10000 games starting with 31 recalls. Fails: 10000, or 100.000 %
Simulated 10000 games starting with 32 recalls. Fails: 9999, or 99.990 %
Simulated 10000 games starting with 33 recalls. Fails: 9982, or 99.820 %
Simulated 10000 games starting with 34 recalls. Fails: 9780, or 97.800 %
Simulated 10000 games starting with 35 recalls. Fails: 7793, or 77.930 %
Simulated 10000 games starting with 36 recalls. Fails: 3120, or 31.200 %
Simulated 10000 games starting with 37 recalls. Fails: 10, or 0.100 %
Simulated 10000 games starting with 38 recalls. Fails: 13, or 0.130 %
Simulated 10000 games starting with 39 recalls. Fails: 17, or 0.170 %
Simulated 10000 games starting with 40 recalls. Fails: 23, or 0.230 %
Simulated 10000 games starting with 41 recalls. Fails: 43, or 0.430 %
Simulated 10000 games starting with 42 recalls. Fails: 66, or 0.660 %
Simulated 10000 games starting with 43 recalls. Fails: 107, or 1.070 %
Simulated 10000 games starting with 44 recalls. Fails: 148, or 1.480 %
Simulated 10000 games starting with 45 recalls. Fails: 192, or 1.920 %
Simulated 10000 games starting with 46 recalls. Fails: 323, or 3.230 %
Simulated 10000 games starting with 47 recalls. Fails: 682, or 6.820 %
Simulated 10000 games starting with 48 recalls. Fails: 2524, or 25.240 %
Simulated 10000 games starting with 49 recalls. Fails: 7823, or 78.230 %
Simulated 10000 games starting with 50 recalls. Fails: 9738, or 97.380 %
Simulated 10000 games starting with 51 recalls. Fails: 10000, or 100.000 %
Simulated 10000 games starting with 52 recalls. Fails: 10000, or 100.000 %
Simulated 10000 games starting with 53 recalls. Fails: 10000, or 100.000 %
Simulated 10000 games starting with 54 recalls. Fails: 10000, or 100.000 %
Simulated 10000 games starting with 55 recalls. Fails: 10000, or 100.000 %
Simulated 10000 games starting with 56 recalls. Fails: 10000, or 100.000 %
Simulated 10000 games starting with 57 recalls. Fails: 10000, or 100.000 %
Simulated 10000 games starting with 58 recalls. Fails: 10000, or 100.000 %
Simulated 10000 games starting with 59 recalls. Fails: 10000, or 100.000 %
Simulated 10000 games starting with 60 recalls. Fails: 10000, or 100.000 %
num_recalls = 10000000
Simulated 10000000 games starting with 36 recalls. Fails: 3186269, or 31.863 %
Simulated 10000000 games starting with 37 recalls. Fails: 11688, or 0.117 %
Simulated 10000000 games starting with 38 recalls. Fails: 13387, or 0.134 %
"""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment