デッキ評価に必要な試合数は?How many games are necessary for deck evaluation?(hearthstone,ハースストーン)

ハースストーンについての記事です。
This is an article about hearthstone.
playhearthstone.com


デッキの組み換えや、オリジナルデッキを作成した時、当然そのデッキの評価を行う必要があります。
つまり、実際にデッキを使用してみてどの程度勝利できるかの検証を行うわけです。
しかし、ゲームの性質上、勝敗はランダム性に影響される部分も多く、例えば3連勝したとしても、デッキが強いのか、運が良かっただけなのかは判断しきれません。
そのためデッキの評価を行うにはある程度の試合数をこなす必要があります。
When recombining the deck or creating the original deck, it is necessary to evaluate the deck.
In other words, we actually verify how much we can win by using the deck.
However, due to the nature of the game, the victory or defeat is affected by randomness in many parts, even if you won three consecutive victories, for example, you can not judge whether the deck is strong or lucky.
Therefore, it is necessary to perform a certain number of games to evaluate the deck.


本記事ではデッキの評価を行う際、何試合程度行えば評価ができるかをシミュレーションによって検証します。
In this article, when evaluating the deck, how many games you can evaluate can be evaluated by simulation.


メタを以下のように定義します。
メタは複数のデッキタイプとそれらの構成比、また、デッキタイプ間の勝率からなります。
つまり、どのデッキタイプがそれぞれどの程度存在し、それぞれのデッキタイプは他のデッキタイプにどの程度勝てるかというものです。
Define the meta as follows.
Meta consists of multiple deck types and their composition ratio, and the winning ratio between deck types.
In other words, each deck type exists to what extent, and how much each deck type can win against other deck types.


分析の条件は記事下部に記載のコードで代替します。言語はpythonです。
The analysis condition is replaced with the code described at the bottom of the article.


結論は以下です。
「デッキの評価を行うための試合数は、そのデッキの真の勝率に依存する。」
「勝率5割を超えているかどうかを評価したい場合、必要な試合数とデッキの真の勝率との関係は図のようになる。」
The conclusion is as follows.
The number of matches to evaluate the deck depends on the true winning percentage of that deck.
If you want to evaluate whether the winning percentage exceeds 50%, the relationship between the number of games required and the true winning percentage of the deck is as shown in the figure.
f:id:Tug-uca:20180328144509p:plain
ただし、横軸はデッキの真の勝率、縦軸は必要な試合数
However, the horizontal axis represents the true win percentage of the deck, and the vertical axis represents the number of required games.


実践への示唆として以下の2つをあげます。
・オリジナルデッキを作成してそれが平均より強いかどうかを検証する場合は30~40戦程度が目安になると考えられる。
・既存デッキタイプのカードの入れかえを評価したい場合は、100戦以上しないと評価ができず、現実的ではない。ゆえにこの場合は、単純な勝率だけでなく、試合中の動きも含めた評価を行う必要がある。
Two suggestions for practice are given below.
· When you create an original deck and verify whether it is stronger than the average it is considered that roughly 30 to 40 war will be a standard.
· If you want to evaluate the replacement of an existing deck type card, you can not evaluate it unless you do 100 or more races, which is not realistic. Therefore, in this case, it is necessary to evaluate not only the simple winning percentage but also the movement during the game.



コードをコピペで実行可能です。
The code can be executed with Copy.

from numpy.random import *

def gene(type_n, ave):
    
    type_n = randint(5, 10)

    meta_exist = [rand() for i in range(type_n)]
    meta_exist = list(map(lambda x: x / sum(meta_exist), meta_exist))

    meta_win_rate = []

    for n in range(type_n):
        tmp=[]
        for m in range(type_n):
            if n==m:
                tmp.append(0.5)
            else:
                nor_rnd = normal(rand()*0.3+0.40,0.05)
                if nor_rnd < 0:
                    nor_rnd = 0
                tmp.append(nor_rnd)
        meta_win_rate.append(tmp)

    return(meta_exist,meta_win_rate)
from numpy.random import *
import numpy as np


def simulation(meta_exist,meta_win_rate):

    my_deck_type = 0

    run_n = 2000
    sim_n = 100

    output = []

    for run in range(run_n):
        output_run = []
        play_count = 0
        win_count = 0
        for n in range(sim_n):
            rnd = rand()
            s = 0
            for your_deck_type in range(len(meta_exist)):
                s = s + meta_exist[your_deck_type]
                if s > rnd:
                    break

            play_count = play_count + 1
            if rand() < meta_win_rate[my_deck_type][your_deck_type]:
                win_count = win_count + 1
            output_run.append(win_count/play_count)
        output.append(output_run)

    truth_win_rate=0
    for n in range(len(meta_exist)):
        truth_win_rate = truth_win_rate + meta_win_rate[my_deck_type][n]*meta_exist[n]

    output_t = list(map(list, zip(*output)))
    return output_t,truth_win_rate
import sys
import matplotlib.pyplot as plt
import numpy as np

meta_n = 50
a = [0 for i in range(meta_n)]
b = [0 for i in range(meta_n)]
for n in range(meta_n):
    
    sys.stdout.write("\r%d/%d" % (n+1 , meta_n))
    sys.stdout.flush()
    
    meta_exist,meta_win_rate = gene(10,0.60)
    output_t,truth_win_rate = simulation(meta_exist,meta_win_rate)

    b[n] = truth_win_rate
    stdev_u = []
    stdev_d = []
    flag = 0
    for m in output_t:
        stdev_u.append(np.mean(m)+np.std(m))
        stdev_d.append(np.mean(m)-np.std(m))
        if flag ==0 and np.mean(m)-np.std(m)>0.45:
            a[n] = output_t.index(m)
            flag = 1

plt.scatter(b,a)
plt.show()