レッドカードって強いの?シミュレーションで検証してみました
はじめに
ポケポケでデッキ構築しているとサカキかナツメかそれともレッドカードか最後の1枚をどれにするか悩むことってありますよね
特に2進化ポケモン完成を遅延する目的でレッドカードを組み込むことがあると思いますがその価値はいったいどれほどでしょうか?
実際にシミレーションを行うプログラムを作成して検証してみました
前提
これからの話は2進化ポケモン一般に当てはまる内容ですが便宜上ミューツーデッキにおける2進化を例に説明します
まずサーナイトの遅延を目的としたレッドカードが強いシチュエーションというのは相手のラルトスもしくはキルリアが場に出た直後のターンで相手の手札が4枚以上のときです
これはポケモンを場に出したターンにはそのポケモンは進化ができないというこのゲームの制約のためです
どうするか?
以前プログラムによるシミレーションの結果最速サナの確率は38%という記事を書きましたがこのときは簡単のためレッドカードを考慮していませんでした
今回このプログラムに上記のシチュエーションが発生した場合に相手の手札にレッドカードがあれば常に使用してくることを仮定してプログラムを修正しどの程度遅延効果が見込めるかを検証してみたいと思いますなお今回も簡単のため以下の制約のもとプログラムを作成しています
- モンスターボール、博士の研究が手札にある時は常にモンスターボール、博士の研究の順序で使用する
- たねポケモンが手札にある時は常にすべて場に出す
- 進化できるときは常に進化する
検証
レッドカードが手に入る確率は?
まずターン別に手札にレッドカードが存在する確率をシミュレーションによって求めます
今回はデッキに含まれるレッドカードの枚数を1枚として検証を行いました
コードはこちらになります
# レッドカードの確率
import random
def simulate(basic_num, red_num):
deck = ['research']*2 + ['ball']*2 + ['red']*red_num + ['basic']*basic_num
deck += ['dummy']*(20-len(deck))
# たねポケモンが1体以上含まれるまで初期手札を生成
while True:
random.shuffle(deck)
hand = deck[:5]
if 'basic' in hand:
break
deck = deck[5:]
for turn in range(1, 100):
if len(deck):
hand.append(deck.pop(0))
# モンスターボール使用
for i in range(hand.count('ball')):
hand.remove('ball')
if 'basic' in deck:
deck.remove('basic')
hand.append('basic')
# 博士の研究使用
if 'research' in hand:
hand.remove('research')
for i in range(min(len(deck), 2)):
hand.append(deck.pop(0))
if 'red' in hand:
return turn
SIMULATE_NUM = 100000
BASIC_NUM = 5
RED_NUM = 1
turns = [simulate(BASIC_NUM, RED_NUM) for i in range(SIMULATE_NUM)]
count = { i: 0 for i in range(1,100)}
for turn in turns:
count[turn] += 1
result = {key: value / SIMULATE_NUM for key, value in count.items()}
sum = 0
red_propability ={}
for key, value in result.items():
sum += value
red_propability[key] = sum
for key, value in red_propability.items():
print(f'{key}ターンまでに手札に存在: {round(value*100, 2)}%')
if(key == 10):
break
実行結果を表にまとめるとこちらになります
1ターン以内に所持している確率 | 34.33% |
2ターン以内に所持している確率 | 43.42% |
3ターン以内に所持している確率 | 50.77% |
4ターン以内に所持している確率 | 58.24% |
5ターン以内に所持している確率 | 65.68% |
6ターン以内に所持している確率 | 73.08% |
7ターン以内に所持している確率 | 80.38% |
8ターン以内に所持している確率 | 87.68% |
9ターン以内に所持している確率 | 94.95% |
なおこの結果はたねポケモン以外の任意のカードについても当てはまります
サーナイト完成の確率は?
次にここで算出をした確率をもとにレッドカードの処理を加えたコードがこちらになります
import random
def simulate(basic_num, is_first):
deck = ['research']*2 + ['ball']*2 + ['ralts']*2 + ['kirlia']*2 + ['gardevoir']*2 + ['basic']*basic_num
deck += ['dummy']*(20-len(deck))
# たねポケモンが1体以上含まれるまで初期手札を生成
while True:
random.shuffle(deck)
hand = deck[:5]
basics_in_hand = list(filter(lambda c: c in ["ralts", 'basic'], hand))
if len(basics_in_hand):
break
deck = deck[5:]
# レッドカードが使用済みか?
is_used = False
# 直前のターンでラルトスorキルリアが場に出たか?
is_do = False
# たねポケモンをセット
field = []
field += basics_in_hand
# ラルトスがセットされたときis_doをTrue
if 'ralts' in basics_in_hand:
is_do = True
for basic in basics_in_hand:
hand.remove(basic)
for turn in range(1, 100):
# レッドカードの処理
# 先手の1ターン目以外 and 直前のターンにラルトスorキルリアが出た and ハンドが4枚以上 and レッドカードが使われていない とき
# そのターンまでにレッドカードを所持している確率で発動
rival_turn = turn - 1 if is_first else turn
if not (is_first and turn == 1) and is_do and 4 <= len(hand) and not is_used and random.random() < red_propability[rival_turn]:
is_used = True
deck += hand
random.shuffle(deck)
hand = deck[:3]
deck = deck[3:]
is_do = False
# ドロー
if len(deck):
hand.append(deck.pop(0))
# モンスターボール使用
for i in range(hand.count('ball')):
hand.remove('ball')
basics_in_deck = list(filter(lambda c: c in ["ralts", 'basic'], deck))
if(len(basics_in_deck)):
basic = basics_in_deck[0]
deck.remove(basic)
hand.append(basic)
# 博士の研究使用
if 'research' in hand:
hand.remove('research')
for i in range(min(len(deck), 2)):
hand.append(deck.pop(0))
# 1ターン以外の時進化の処理
if turn!= 1:
evolutions = []
for candidate in hand:
if candidate == 'kirlia' and 'ralts' in field:
field.remove('ralts')
evolutions.append('kirlia')
# キルリアが場に出た時is_doをTrue
is_do = True
if candidate == 'gardevoir' and 'kirlia' in field:
field.remove('kirlia')
evolutions.append('gardevoir')
for c in evolutions:
hand.remove(c)
field += evolutions
# たねポケモンを出す
basics_in_hand = list(filter(lambda c: c in ["ralts", 'basic'], hand))
field += basics_in_hand
for basic in basics_in_hand:
hand.remove(basic)
# ラルトスが場に出されたときis_doをTrueに
if 'ralts' in basics_in_hand:
is_do = True
# サーナイトが場にいるときターン数を返してシミュレーションを終了
if 'gardevoir' in field:
return turn
SIMULATE_NUM = 100000
BASIC_NUM = 3
IS_FIRST = False
turns = [simulate(BASIC_NUM, IS_FIRST) for i in range(SIMULATE_NUM)]
count = { i: 0 for i in range(1,100)}
for turn in turns:
count[turn] += 1
result = {key: value / SIMULATE_NUM for key, value in count.items()}
print(f'追加のたねポケモンが{BASIC_NUM}体の場合')
sum = 0
for key, value in result.items():
sum += value
print(f'{key}ターン目で揃う確率: {round(value*100, 2)}%(累計: {round(sum*100, 2)}%)')
if key == 10:
break
なお前回のコードでは先攻後攻の考慮はされていませんが今回の変更では区別するように変更しました
レッドカードを考慮すると後攻の場合先行の場合と異なり1ターン開始前にレッドカードを使用される可能性があるという非対称性があるからです
実行結果を表にまとめるとこちらになります
定番のミューツーデッキのたねポケモン5枚の構成で実行しています
レッドカード無 | レッドカード有(先手) | レッドカード有(後手) | |
---|---|---|---|
1ターン以内に完成する確率 | 0.00% | 0.00% | 0.00% |
2ターン以内に完成する確率 | 0.00% | 0.00% | 0.00% |
3ターン以内に完成する確率 | 38.34% | 33.51% | 31.55% |
4ターン以内に完成する確率 | 52.83% | 46.70% | 44.45% |
5ターン以内に完成する確率 | 65.85% | 58.88% | 56.62% |
6ターン以内に完成する確率 | 77.35% | 69.70% | 67.72% |
7ターン以内に完成する確率 | 86.74% | 78.70% | 77.23% |
8ターン以内に完成する確率 | 93.66% | 85.84% | 84.94% |
9ターン以内に完成する確率 | 97.74% | 91.17% | 90.66% |
レッドカード持ちの相手に対して後攻2ターン目でのサーナイト完成いわゆる最速サナの確率は7%ほど下がることがわかりました
全体的にみてもおおよそ0.5ターン程度の遅延効果があることがわかります
また後手のほうが影響が大きいという結果も興味深いですね
まとめ
いかがでしたか?
思っていたよりも強いなと感じる方が多いのではないでしょうか?
ぜひこの結果を参考にレッドカード使ってみてください!
Discussion