There is a pretty rad game called Hearthstone — its a digital card game made by Blizzard. Similar to Magic the Gathering two players face off using (usually) preconstructed decks of creatures and spells to defeat the opponent.
There is a mechanic in this game called discover, in which you are presented with three choices and get to select one.
For example, a card like Choose Your Path can be a “toolbox” card — if you draw it in the late game it can be a large creature or if you are getting swarmed by your opponent it can be an area-of-effect style spell. Getting this flexibility has costs, however, because it puts the selection into your hand (effectively taxing you one mana) and doesn’t guarantee you the spell you need. This flexibility makes it a powerful and skill-testing card.
In the new set they revealed a new card: A New Challenger… and discussions cropped up about how good this card truly is
Since most discover cards have the “toolbox” aspect to them we can’t easily rank the cards offered. However with this card you just want the biggest minion every time — which should be able to determine pretty accurately how good this card is.
To do this we need to use math. So to restate the problem:
Given a deck of size N with cards numbered 1-N, what is the expected value of the largest card in a three card hand?
We get that the expected value of a hand of h cards from a pool of p cards is
This represents taking the difference between the number of combinations of a deck of cards of n-1 and n cards. Notably, all the cards that are added in these combinations will have the n in them — otherwise they could be represented with n-1! These hands will have n as their largest card (its the largest it knows) and so the value of the hand must be n.
The probability of getting a score n from a pool of p cards with a hand of size h is P(p,h,n), given by:
In essence, this says that the probability is the (hand_size / pool_of_cards) after you remove the probability that its a higher value P(p,h,(n+1 -> p))
note that it shows the asymptote as being .755, it should be .75. This is the same output from the EV equation but divided by N to make it more comparable to one another
Okay so what does this tell us? The card will be, on average, 75% of the best card available.
Therefore, A New Challenger can be evaluated as getting you the 75th percentile of the ordered 6-Cost minions in the Hearthstone standard format with Taunt and Divine Shield.
What if Discover showed you more than 3 cards?
Logically, you would get a better card. Here is if you could see four cards:
And here is a similar figure but showing for a large range of hand sizes:
This gives you the equation:
Here is the source code
import itertools, math
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
import numpy as np
f = math.factorial
return f(n) / f(r) / f(n-r)
#Deck of size d, hand of size h
delta = 0
points = 0
total_combs = 0
for i in range(h,d+1):
delta = nCr(i,h) - total_combs
total_combs += delta
points += delta*i
return points / total_combs / d
#Deck of size d, hand of size h
ev = 0
p_card = [0 for i in range(d)]
for n in range(d-1,0,-1): p_card[n] = (h/(n+1))*(1-sum(p_card[n+1:]))
for c in range(d): ev += p_card[c]*(c+1)
return ev / d
end_val_1 = EV_recursive(10000,3)
end_val_2 = EV_recursive(10000,4)
rolls = 3
max_sided_die = 40
y_1 = [EV(rolls,i) for i in range(rolls,max_sided_die)]
y_2 = [EV(4,i) for i in range(4,max_sided_die)]
x_1 = [i for i in range(rolls,max_sided_die)]
x_2 = [i for i in range(4,max_sided_die)]
fig = plt.figure()
ax = fig.add_subplot(111)
#Plotting 3 card hand
p = np.polyfit([0,1], [end_val_1,end_val_1], 1)
ax.annotate("y = " + str(end_val_1)[:6],xy=(3,end_val_1+0.01))
blue_patch = mpatches.Patch(color='blue', label='3 cards to select from')
orange_patch = mpatches.Patch(color='orange', label='4 cards to select from')
#Plotting 4 card hand
p = np.polyfit([0,1], [end_val_2,end_val_2], 1)
ax.annotate("y = " + str(end_val_2)[:6],xy=(3,end_val_2+0.01))
plt.scatter(x_2,y_2, color = 'orange')
plt.title('EV for selecting 3 or 4 cards from a deck of N cards\nnumbered 1-N and getting points equal to the largest one')
plt.xlabel("N\nnumber of cards")
plt.ylabel('EV / N\npercent of maximum score expected')