新マリガンでトロンの揃う確率をモンテカルロシミュレーションで解く


こういう、どう考えても解析的に解いた方がいいやつをモンテカルロ法で近似したくなるのはカードゲーマーの性質ですね。しかしゲームの流れに沿ってプログラムを書けるので、キープ基準とか考え始めると素直に計算するよりこういう方法の方が楽です。新マリガンと旧マリガンで10万回ずつ試行しました。

#新マリガン
import random

def tron():
    urza1 = [1,2,3,4]
    urza2 = [5,6,7,8]
    urza3 = [9,10,11,12]
    karn = [13,14,15,16]
    deck = range(60)
    hands = random.sample(deck, 7)
    if (len(set(urza1) & set(hands)) != 0) and (len(set(urza2) & set(hands)) != 0) and (len(set(urza3) & set(hands)) != 0) and (len(set(karn) & set(hands)) != 0):
        return (1)
    else:
        hands = random.sample(deck, 7)
        if (len(set(urza1) & set(hands)) != 0) and (len(set(urza2) & set(hands)) != 0) and (len(set(urza3) & set(hands)) != 0) and (len(set(karn) & set(hands)) != 0):
            return (1)
        else:
            hands = random.sample(deck, 7)
            if (len(set(urza1) & set(hands)) != 0) and (len(set(urza2) & set(hands)) != 0) and (len(set(urza3) & set(hands)) != 0) and (len(set(karn) & set(hands)) != 0):
                return (1)
        return(0)

iters = 100000
tenhou = [tron() for i in range(iters)]
print(sum(tenhou)/iters * 100)

3.895%

import random
#旧マリガン 占術はだるいので考えない

def tron():
    urza1 = [1,2,3,4]
    urza2 = [5,6,7,8]
    urza3 = [9,10,11,12]
    karn = [13,14,15,16]
    deck = range(60)
    hands = random.sample(deck, 7)
    if (len(set(urza1) & set(hands)) != 0) and (len(set(urza2) & set(hands)) != 0) and (len(set(urza3) & set(hands)) != 0) and (len(set(karn) & set(hands)) != 0):
        return (1)
    else:
        hands = random.sample(deck, 6)
        if (len(set(urza1) & set(hands)) != 0) and (len(set(urza2) & set(hands)) != 0) and (len(set(urza3) & set(hands)) != 0) and (len(set(karn) & set(hands)) != 0):
            return (1)
        else:
            hands = random.sample(deck, 5)
            if (len(set(urza1) & set(hands)) != 0) and (len(set(urza2) & set(hands)) != 0) and (len(set(urza3) & set(hands)) != 0) and (len(set(karn) & set(hands)) != 0):
                return (1)
        return(0)

iters = 100000
tenhou = [tron() for i in range(iters)]
print(sum(tenhou)/iters * 100)

2.127%

新マリガン:3.895%、旧マリガン:2.127%となりました。

占術もキープ基準も考えてないのであれですが、「一枚でも揃ってない場合は追いかける」と言うガバガバな戦略の場合、初手でトロンが揃う確率が2倍弱上がるようです。結構違うな。