こんにちは。くろこんです。今回はオンラインカードゲーム、シャドウバース・ビヨンドの2pickの報酬の分析です。高校数学の範囲で分かる内容となっています。
計算には Python を使っていきます。
2pick とは
いわゆるリミテッドと呼ばれるカードゲームのフォーマットです。ランダムにカードを取得して、そこからデッキを作り遊びます。
このタイプのフォーマットでは、大体報酬が用意されているのが通例で、その量は勝利数に応じます。この勝利数を勝率へ変換した場合にどうなるのか、という問題です。
シャドウバース・ビヨンドでは2敗する、または7勝するまで対戦が可能です。
勝利数に応じた報酬は以下のようになります。
def gem():
return [100, 300, 500, 700, 850, 1000, 1250, 1500]
(シャドウバースのお金の単位はルピですが、単位無しで扱っていきます)
0勝だと100で、7勝だと1500ということです。他にもカードパックがもらえたりしますが、今回は無限に遊ぶための条件ということで、お金の報酬だけを計算します。
確率の計算
まず、場合分けを考えます。一番単純な、勝利数での場合分けをします。勝率を$p$として計算していきます。
0勝の場合
勝率 $p$ ということは、敗率は $1-p$ です。0回勝つ確率を $q_0$ とすると、
q_0 = (1-p)^2
となります。
1勝の場合
2敗するまで、なので、2試合目までが1勝1敗で、3試合目が負け、となります。
q_1= \ _2 C_1 p(1-p)\ \ (1-p) = 2p(1-p)^2
2勝の場合
2敗するまで、なので、3試合目までが2勝1敗で、4試合目が負け、となります。
q_2= \ _3 C_1 p^2(1-p)\ \ (1-p) = 3p^2(1-p)^2
0~6勝の場合
6勝までは、最後の試合が負け、という同じ性質を持つので、一般化して表しましょう。
q_n= \ _{n+1} C_1 p^n(1-p)\ \ (1-p) = (n+1)p^n(1-p)^2
7勝の場合
7連勝する場合と、1敗して最後に勝つ場合の2通りがあります。
q_7= p^7 + \ _7 C_1 p^6(1-p)\ \ p = p^7 (8-7p)
もしくは、$\sum^6_{n=0} q_n$ を計算して 1 から引いてもよいです。
\sum^6_{n=0}q_n = (1-p)^2 (1+2p+3p^2+4p^3+5p^4+6p^5+7p^6)
\ \ \ \ \ \ \ \ = (1-p) (1+p+p^2+p^3+p^4+p^5+p^6-7p^7)
= 1-p^7 -7p^7+7p^8 = 1 - p^7 (8 - 7p) \ \ \ \ \ \ \
Python で期待値の計算
先ほど計算した確率を使って、期待値を計算していきます。
def calc(p):
g = gem()
pm1 = 1-p
pp = 1
exg = 0
for w in range(7):
q = pp * pm1 * pm1 * (w + 1)
pp = pp * p
exg = exg + q * g[w]
exg = exg + pp * (8 - 7 * p) * g[7]
return exg
プログラム中の pp は、$p^n$ を使いまわすために計算しています。
これで、$p$ の値をしらみつぶしに探していくと、無限に遊べる勝率がわかります。今のところ 2pick のプレイ料金は 1000 なので、勝率 75.7 %で報酬期待値が 1000.0656733244928 になります。
検算
プログラミングの世界では、計算したから終了、というのは非常に危険な行為です。何かしらの検算がおすすめです。
今回は勝敗を乱数で生成したシミュレーションで確認します。
def sim(p,itr):
g = gem()
v = 0 #報酬累計
c = 0 #入場数
w = 0 #勝利数
l = 0 #敗北数
for i in range(itr):
x = random.random()
if x < p:
w = w + 1
else:
l = l + 1
if l == 2 or w == 7:
v = v + g[w]
w = 0
l = 0
c = c + 1
print(v / c, v, c, itr)
1001.3594341453945 165072100 164848 1000000
勝率 75.7 %で 1000000 試合すると、164848 入場で報酬が 165072100 になって、平均はほぼ 1000 となりました。(ランダムなので毎回結果は変わります)
おまけ python での勝率探索結果
# この数値や3桁以上の近似値などを載せる場合は、この記事の URL などを併記してください
0.7569747594467667
おまけ 2pick は得か損か
パック価格が 500 であることから、報酬を書き換えます。
def gem():
return [600, 800, 1000, 1200, 1350, 1500, 1750, 2500]
これで $p=0.5$ で計算します。
999.0234375
……微妙ですね。
おまけ 外部サイト様との比較
計算の結果が載っているサイト様がありました。勝率 75 % のとき 981.9 は同じ結果になっています。