ディスクアップのシミュレータ

お世話になっております、スログラミングです。

今更ながらディスクアップのシミュレータを作ってみました。
数値等はスログラミング調べということで、皆様で適当な数値に変えながら色々遊んでいただければと思います。
作成したコードをGoogle Colaboratoryに貼り付けると簡単に遊べます。
Google Colaboratoryの簡単な使い方はこちら→スマホで設定判別ツールを使おう

では早速Pythonでコーディングしていきましょう。
※中身の数値等はスログラミング調べなので、実機とは異なる可能性があります。

今回のアジェンダはこちら。
0. はじめに(def文とは?)
1. 同色BB処理
2. 通常・ART時処理
3. ループ処理
4. 今回作成したコード
5. 結果の確認


0. はじめに(def文とは?)

シミュレータの説明に入る前に、def文について説明しておきます。
def文とは自分オリジナルの関数を定義できる方法です。
defは英語のdefine(=定義する)の略ですね。(多分)

これだけだと理解しきれないと思いますので、平均値算出を例に説明していきます。

問題:2と3の平均値は?
例えば、真面目にやるとこんな感じで算出できます。
    平均 = (2 + 3) / 2

    print(平均)

ただ、毎回この計算式を書くのって結構めんどくさいと思います。
今回は1行で済みますが、もっと複雑な計算だといっそう面倒ですし、書き間違いも発生しそうです。

そんな時はライブラリの出番です。
平均値であれば、numpyライブラリのmean関数を用いて、このように記載できます。
    import numpy as np
    np.mean([2, 3])

では、もしnumpyライブラリがなかったら?

そうです。そんな時に自分で関数を作れるのがdef文です。
今回の例題だと、こうなります。
「def 関数名():」で処理を記載しておけば、「関数名()」を実行するだけで簡単に使えます。
関数の戻り値は、「return 戻り値」で記載することで欲しい情報を得ることができます。
今回の場合は、平均値を戻り値として返すように設定しています。
    def 平均():
        y = (2 + 3) / 2
    
        return y
    
    print(平均())

ちなみに、変数の値を投げることもできます。
例えば、以下のように記載すると、好きな値の平均値を算出できます。
    def 平均2(a, b):
        y = (a + b) / 2
    
        return y
    
    a = 2
    b = 3
    
    print(平均2(a, b))
さらに、戻り値は複数の値を設定することも可能です。
例えば、以下のように記載すると、平均値とともに、”a”と”b”に入っている値も出力できます。
戻り値は配列形式になっているので、関数名の後ろに[0]のような形で指定すれば欲しい位置の値だけを取得できます。
    def 平均3(a, b):
    y = (a + b) / 2

    return y, a, b


    a = 2
    b = 3

    print(平均3(a, b))    # 出力は"(2.5, 2, 3)"となる
    print(平均3(a, b)[0]) # 出力は"2.5"となる

前置きが長くなりましたが、つまりはこんな感じのプログラムを作成したいと考えています。
ボーナスの処理や通常時・ART時の抽選処理をdef文として作成しておいて、メインの処理は乱数抽選とループ処理だけ記載すれば多少楽にコーディングできる(と思う)という狙いです。


    # BBの処理
    def BB():
        # 差枚数やDZ・DTのゲーム数を返す
    
    # RBの処理
    def RB(ART, Total, DT):
        # 差枚数やDTのゲーム数を返す
    
    # 異色BBの処理
    def IBB(ART, Total, DT):
        # 差枚数やDTのゲーム数を返す
    
    # 抽選処理
    def Normal(rand, ART, Total, DZ, DT, Invest, Bita):
        # ボーナスや小役の抽選結果を返す
    
    if __name__ == "__main__":
        # 試行条件の設定とループ処理

1. 同色BB処理

ここから1個ずつdef文を作成していきますが、説明としてはみんな大好き同色BBだけ記載しておきます。
(RBや異色BBはDZ部分を除いて数値をちょっといじればOKなので。)

ディスクアップのBBは以下の仕様となっています。

1. 最大枚数獲得手順実施で251枚獲得
2. BB(28G)間は1/3でreadyが発生し、ビタ押し成功でDZ上乗せ(ビタ失敗でも1/3で救済。ART中はビタ不要で成功扱い)
3. 通常時は1/2でDT獲得、ART中は100%でDT獲得


これらの仕様から、とりあえず引数と戻り値はこんな感じで準備しておけばよさそうですね。
    # BBの処理
    def BB(ART, Total, DZ, DT, Bita):
        return Total, DZ, DT
変数 内容
ART ART中か否かのフラグ(1:ART中、0:通常時)
Total 現在の差枚数
DZ DZの残ゲーム数
DT DTの残ゲーム数
Bita ビタ押しの成功率
Invest 投入枚数(出玉率を算出する用)

1. 最大枚数獲得手順実施で251枚獲得

作成した同色BB関数の中に同色BBの仕様を盛り込んでいきます。
まずは、獲得枚数の処理から。
とはいえこれは簡単ですね。現在の差枚数にBBの獲得枚数251枚を足せば終わりです。
    # BBの処理
    def BB(ART, Total, DZ, DT, Bita):
        # BBの獲得枚数を加算
        Total = Total + 251
    
        return Total, DZ, DT

2. BB(28G)間は1/3でreadyが発生し、ビタ押し成功でDZ上乗せ(ビタ失敗でも1/3で救済。ART中はビタ不要で成功扱い)

続いてready発生時の処理を追加していきます。
やや複雑なので、一旦フローチャートを書いてみます。
流れはこんな感じですね。
readyが発生するか?」「ビタ押し成功するか?」「救済に引っかかるか?」の3段階の条件分岐が必要となります。

コードは以下のような形にしてみました。
条件分岐のタイミング毎に乱数を発生させ、条件を満たす乱数を取得したときにだけ次の条件分岐に進むようにしています。
なお、厳密には通常時とART中ではDZ上乗せの振分は違うらしいです。
が、トータルで乗るG数の期待値は同じらしいので、今回はDZ上乗せの振分も同じとして作成しています。
    def BB(ART, Total, DZ, DT, Bita):
        # BBの獲得枚数を加算
        Total = Total + 251

        # DZ加算処理(BBのG数28G)
        for i in range(28):
            # 1/3でready発生
            if random.randint(1,3) == 1:
                Bitarand = random.randint(1, 100)

                # ビタ成功orART中orビタ失敗時の1/3救済時はDZ上乗せ
                if Bitarand <= Bita or ART == 1 or (Bitarand > Bita and random.randint(1,3) == 1):
                    DZrand = random.randint(1, 1000)
                    # DZ上乗せ振り分け
                    if DZrand <= 270:
                        DZ = DZ + 3
                    elif 270 < DZrand <= 630:
                        DZ = DZ + 5
                    ・・・
                    ・・・

        return Total, DZ, DT

3. 通常時は1/2でDT獲得、ART中は100%でDT獲得

最後にDTの処理を作成すればBBの関数は完成です。
100G当選のときだけ、ループ抽選となるのが若干複雑ですが、それ以外はシンプルですね。
ループ抽選の部分は、while文を使用して上乗せ抽選に漏れるまで処理を続けるような記載にしています。
また、通常時とART中ではDT上乗せのトータルの期待値も変わりそうなので、通常時とART中で振分を変えています。
    def BB(ART, Total, DZ, DT, Bita):
        ・・・
        ・・・
        # DT加算処理
        # 通常時のBB
        if ART == 0:
            # BB当選時の50.4%でDT突入
            if random.randint(1, 1000) <= 504:
                DTrand = random.randint(1, 1000)
                # DTのG数振り分け
                if DTrand <= 388:
                    DT = DT + 20
                elif 388 < DTrand <= 636:
                    DT = DT + 40
                ・・・
                ・・・
                elif 907 < DTrand <= 1000:
                    DT = DT + 100
                    # 100G当選の時だけループ抽選
                    DTlooprand = random.randint(1, 1000)
                    if DTlooprand <= 488:
                        while random.randint(1,1000) <= 4:
                            DT = DT + 100
                    elif 488 < DTlooprand <= 988:
                        while random.randint(1,1000) <= 330:
                            DT = DT + 100
                    ・・・
                    ・・・
        # ART中のBB
        elif ART == 1:
            DTrand = random.randint(1, 1000)
            # DTのG数振り分け
            if DTrand <= 871:
                DT = DT + 20
            ・・・
            ・・・

        return Total, DZ, DT

2. 通常・ART時処理

今回は通常時とART中のボーナスや小役の処理もdef文で作ってみました。
小役の乱数範囲の設定や、抽選処理は今までと同じなので説明は割愛します。
※ART中と通常時でリプレイの当選確率が大きく変わることに注意

↓のコードのように、def文の中で別のdef文を呼び出すことも可能です。
今回作成した同色BB関数では、戻り値として、現在の差枚・DZの残G数・DTの残G数が返ってきます。
配列形式で順番に格納されているので、現在の差枚が[0]、DZの残G数が[1]といった形で参照が可能です。
    # 抽選処理
    def Normal(rand, ART, Total, DZ, DT, Invest, Bita):
        # 各役の乱数範囲設定
        ・・・
        ・・・
    
        # 同色BBの時
        if 同色BB範囲_下 <= rand <= 同色BB範囲_上:
            # ボーナス察知で次Gに1.5枚消費
            Total = Total - 1.5
            Invest = Invest + 1.5
    
            # BB関数を呼んで結果を受け取る
            BBResult = BB(ART, Total, DZ, DT, Bita)
            Total = BBResult[0]
            DZ = BBResult[1]
            DT = BBResult[2]
    
            # ART獲得したらART状態に移行する
            if DZ + DT > 0:
                ART = 1

        return ART, Total, DZ, DT, Invest

3. ループ処理

最後にループ処理を作成し、これまで作成したdef文を呼び出せばディスクアップのシミュレータは完成です。
今回はART中も含めた試行回数を設定したいので、while文でループを回していきます。
抽選結果は乱数を通常時・ART中の関数に投げれば取得できるのでかなりシンプルになっていると思います。
(「# 抽選結果を取得」の部分)

ARTの終了条件が「DZとDTの残G数が0になったとき」だけでなく「1500G完走したとき」も必要なのに注意が必要です。
    if __name__ == "__main__":
        # 試行条件の設定
        # ビタ押し成功率[%]
        Bita = 60
        # 試行回数
        loop = 10000000

        # 結果を入れる箱の準備
        Slump = [] # 1G毎の差枚を入力
        Total = 0   # 現在の差枚を入力
        Invest = 0  # 投入枚数を入力
        ・・・
        ・・・

        # ループ処理の準備
        DZ = 0  # DZのG数を入力
        DT = 0  # DTのG数を入力
        ART = 0    # ARTフラグ(1:ART中、0:通常時)
        Limit = 1   # ARTの連続G数を入力(1500Gで完走させる)
        i = 1   # 総回転数を入力

        # ループ処理
        while i <= loop:
            # 1回転あたり3枚使用
            Total = Total - 3
            Invest = Invest + 3

            # 乱数の取得
            rand = random.randint(1, 65536)

            # 当否判定処理
            # 通常時の処理
            if ART == 0:
                # 抽選結果を取得
                Result = Normal(rand, ART, Total, DZ, DT, Invest, Bita)

                # 各数値を抽選結果に更新
                ART = Result[0]
                Total = Result[1]
                DZ = Result[2]
                DT = Result[3]
                Invest = Result[4]

                Slump.append(Total)

            elif ART ==1:
                # ART回数が0になるまでループ
                while DZ + DT > 0:
                    # 1回転あたり3枚使用
                    Total = Total - 3
                    Invest = Invest + 3

                    # 乱数の取得
                    rand = random.randint(1, 65536)

                    # 抽選結果を取得
                    Result = Normal(rand, ART, Total, DZ, DT, Invest, Bita)

                    # 各数値を抽選結果に更新
                    ART = Result[0]
                    Total = Result[1]
                    DZ = Result[2]
                    DT = Result[3]
                    Invest = Result[4]

                    Slump.append(Total)

                    # ART残回数減算処理
                    # DTから消化する
                    if DT > 0:
                        DT = DT - 1
                    else:
                        DZ = DZ - 1

                    # ARTの残G数がなくなるか、完走でARTを抜ける
                    if DT == 0 and DZ == 0:
                        ART = 0
                        Limit = 0
                    elif Limit >= 1500:
                        ART = 0
                        Limit = 0
                        print("完走")

                    # ART中も総回転数に加算
                    i = i + 1

                    # ARTの連続G数を加算
                    Limit = Limit + 1

            # 総回転数を加算
            i = i + 1

4. 今回作成したコード

今回作成したコードはこちら。
スランプグラフと出玉率(機械割)が出力されるようにしています。
また、後述しますが、DZの上乗せ振分をビタ成功時と救済時で変更できるようにしています。
    # coding: UTF-8
    import random
    import numpy as np
    import pylab
    
    # BBの処理
    def BB(ART, Total, DZ, DT, Bita):
        # BBの獲得枚数を加算
        Total = Total + 251
    
        # DZ加算処理(BBのG数28G)
        for i in range(28):
            # 1/3でready発生
            if random.randint(1,3) == 1:
                Bitarand = random.randint(1, 100)
    
                # ビタ成功orART中orビタ失敗時の1/3救済時はDZ上乗せ
                if Bitarand <= Bita or ART == 1:
                    DZrand = random.randint(1, 1000)
                    # DZ上乗せ振り分け
                    if DZrand <= 270:
                        DZ = DZ + 3
                    elif 270 < DZrand <= 630:
                        DZ = DZ + 5
                    elif 630 < DZrand <= 930:
                        DZ = DZ + 7
                    elif 930 < DZrand <= 987:
                        DZ = DZ + 10
                    elif 987 < DZrand <= 994:
                        DZ = DZ + 20
                    elif 994 < DZrand <= 998:
                        DZ = DZ + 30
                    elif 998 < DZrand <= 1000:
                        DZ = DZ + 50
                # ビタ失敗時の救済処理(1/3でDZ上乗せ)
                # おそらく救済時の上乗せは優遇されているので振分を変更
                elif Bitarand > Bita and random.randint(1,3) == 1:
                    DZrand = random.randint(1, 1000)
                    # DZ上乗せ振り分け
                    if DZrand <= 230:
                        DZ = DZ + 3
                    elif 230 < DZrand <= 560:
                        DZ = DZ + 5
                    elif 560 < DZrand <= 850:
                        DZ = DZ + 7
                    elif 850 < DZrand <= 907:
                        DZ = DZ + 10
                    elif 907 < DZrand <= 924:
                        DZ = DZ + 20
                    elif 924 < DZrand <= 958:
                        DZ = DZ + 30
                    elif 958 < DZrand <= 1000:
                        DZ = DZ + 50
    
        # DT加算処理
        # 通常時のBB
        if ART == 0:
            # BB当選時の50.4%でDT突入
            if random.randint(1, 1000) <= 504:
                DTrand = random.randint(1, 1000)
                # DTのG数振り分け
                if DTrand <= 388:
                    DT = DT + 20
                elif 388 < DTrand <= 636:
                    DT = DT + 40
                elif 636 < DTrand <= 822:
                    DT = DT + 60
                elif 822 < DTrand <= 907:
                    DT = DT + 80
                elif 907 < DTrand <= 1000:
                    DT = DT + 100
                    # 100G当選の時だけループ抽選
                    DTlooprand = random.randint(1, 1000)
                    if DTlooprand <= 488:
                        while random.randint(1,1000) <= 4:
                            DT = DT + 100
                    elif 488 < DTlooprand <= 988:
                        while random.randint(1,1000) <= 330:
                            DT = DT + 100
                    elif 488 < DTlooprand <= 988:
                        while random.randint(1,1000) <= 800:
                            DT = DT + 100
        # ART中のBB
        elif ART == 1:
            DTrand = random.randint(1, 1000)
            # DTのG数振り分け
            if DTrand <= 871:
                DT = DT + 20
            elif 871 < DTrand <= 965:
                DT = DT + 40
            elif 965 < DTrand <= 988:
                DT = DT + 60
            elif 988 < DTrand <= 992:
                DT = DT + 80
            elif 992 < DTrand <= 1000:
                DT = DT + 100
                # 100G当選の時だけループ抽選
                DTlooprand = random.randint(1, 1000)
                if DTlooprand <= 488:
                    while random.randint(1,1000) <= 4:
                        DT = DT + 100
                elif 488 < DTlooprand <= 988:
                    while random.randint(1,1000) <= 330:
                        DT = DT + 100
                elif 488 < DTlooprand <= 988:
                    while random.randint(1,1000) <= 800:
                        DT = DT + 100
    
        return Total, DZ, DT
    
    # RBの処理
    def RB(ART, Total, DT):
        # RBの獲得枚数を加算
        Total = Total + 103
    
        # DT加算処理
        # ART中はDTが付加される
        if ART == 1:
            DTrand = random.randint(1, 1000)
            # DTのG数振り分け
            if DTrand <= 934:
                DT = DT + 20
            elif 934 < DTrand <= 981:
                DT = DT + 40
            elif 981 < DTrand <= 993:
                DT = DT + 60
            elif 993 < DTrand <= 996:
                DT = DT + 80
            elif 996 < DTrand <= 1000:
                DT = DT + 100
                # 100G当選の時だけループ抽選
                DTlooprand = random.randint(1, 1000)
                if DTlooprand <= 488:
                    while random.randint(1,1000) <= 4:
                        DT = DT + 100
                elif 488 < DTlooprand <= 988:
                    while random.randint(1,1000) <= 330:
                        DT = DT + 100
                elif 488 < DTlooprand <= 988:
                    while random.randint(1,1000) <= 800:
                        DT = DT + 100
        elif ART == 0:
            DT = DT
    
        return Total, DT
    
    # 異色BBの処理
    def IBB(ART, Total, DT):
        # BBの獲得枚数を加算
        Total = Total + 251
    
        # DT加算処理
        # 通常時の異色BB
        if ART == 0:
            # 1/2でDT当選
            if random.randint(1, 2) == 1:
                DTrand = random.randint(1, 1000)
                # DTのG数振り分け
                if DTrand <= 250:
                    DT = DT + 40
                elif 250 < DTrand <= 500:
                    DT = DT + 60
                elif 500 < DTrand <= 750:
                    DT = DT + 80
                elif 750 < DTrand <= 1000:
                    DT = DT + 100
                    # 100G当選の時だけループ抽選
                    DTlooprand = random.randint(1, 1000)
                    if DTlooprand <= 488:
                        while random.randint(1,1000) <= 4:
                            DT = DT + 100
                    elif 488 < DTlooprand <= 988:
                        while random.randint(1,1000) <= 330:
                            DT = DT + 100
                    elif 488 < DTlooprand <= 988:
                        while random.randint(1,1000) <= 800:
                            DT = DT + 100
        # ART中の異色BB(同色BBと同じ)
        elif ART == 1:
            DTrand = random.randint(1, 1000)
            # DTのG数振り分け
            if DTrand <= 871:
                DT = DT + 20
            elif 871 < DTrand <= 965:
                DT = DT + 40
            elif 965 < DTrand <= 988:
                DT = DT + 60
            elif 988 < DTrand <= 992:
                DT = DT + 80
            elif 992 < DTrand <= 1000:
                DT = DT + 100
                # 100G当選の時だけループ抽選
                DTlooprand = random.randint(1, 1000)
                if DTlooprand <= 488:
                    while random.randint(1,1000) <= 4:
                        DT = DT + 100
                elif 488 < DTlooprand <= 988:
                    while random.randint(1,1000) <= 330:
                        DT = DT + 100
                elif 488 < DTlooprand <= 988:
                    while random.randint(1,1000) <= 800:
                        DT = DT + 100
    
        return Total, DT
    
    # 抽選処理
    def Normal(rand, ART, Total, DZ, DT, Invest, Bita):
        # ボーナス確率の設定
        同色BB = 299
        異色BB = 8192
        REG = 496.5
    
        # 小役確率の設定
        リプレイ = 7.27  # リーチ目リプレイ含
        三択9枚役 = 11.8
        共通9枚役 = 20.0
        チェリー = 26.0
        スイカ = 46.9
    
        ART中リプレイ = 1.57  # 押し順リプレイとリーチ目リプレイ含
        パンク1枚役 = 13.1
    
        # 乱数範囲の設定準備
        同色BB範囲 = round(65536 / 同色BB)
        異色BB範囲 = round(65536 / 異色BB)
        REG範囲 = round(65536 / REG)
        リプレイ範囲 = round(65536 / リプレイ)
        三択9枚役範囲 = round(65536 / 三択9枚役)
        共通9枚役範囲 = round(65536 / 共通9枚役)
        チェリー範囲 = round(65536 / チェリー)
        スイカ範囲 = round(65536 / スイカ)
        ART中リプレイ範囲 = round(65536 / ART中リプレイ)
        パンク1枚役範囲 = round(65536 / パンク1枚役)
    
        # 乱数範囲の設定
        同色BB範囲_下 = 1
        同色BB範囲_上 = 同色BB範囲_下 + 同色BB範囲 - 1
        異色BB範囲_下 = 同色BB範囲_上 + 1
        異色BB範囲_上 = 異色BB範囲_下 + 異色BB範囲 - 1
        REG範囲_下 = 異色BB範囲_上 + 1
        REG範囲_上 = REG範囲_下 + REG範囲 - 1
        リプレイ範囲_下 = REG範囲_上 + 1
        リプレイ範囲_上 = リプレイ範囲_下 + リプレイ範囲 - 1
        三択9枚役範囲_下 = リプレイ範囲_上 + 1
        三択9枚役範囲_上 = 三択9枚役範囲_下 + 三択9枚役範囲 - 1
        共通9枚役範囲_下 = 三択9枚役範囲_上 + 1
        共通9枚役範囲_上 = 共通9枚役範囲_下 + 共通9枚役範囲 - 1
        チェリー範囲_下 = 共通9枚役範囲_上 + 1
        チェリー範囲_上 = チェリー範囲_下 + チェリー範囲 - 1
        スイカ範囲_下 = チェリー範囲_上 + 1
        スイカ範囲_上 = スイカ範囲_下 + スイカ範囲 - 1
        ART中リプレイ範囲_下 = スイカ範囲_上 + 1
        ART中リプレイ範囲_上 = ART中リプレイ範囲_下 + ART中リプレイ範囲 - 1
        パンク1枚役範囲_下 = ART中リプレイ範囲_上 + 1
        パンク1枚役範囲_上 = パンク1枚役範囲_下 + パンク1枚役範囲 - 1
    
        # 同色BBの時
        if 同色BB範囲_下 <= rand <= 同色BB範囲_上:
            # ボーナス察知で次Gに1.5枚消費
            Total = Total - 1.5
            Invest = Invest + 1.5
    
            # BB関数を呼んで結果を受け取る
            BBResult = BB(ART, Total, DZ, DT, Bita)
            Total = BBResult[0]
            DZ = BBResult[1]
            DT = BBResult[2]
    
            # 当選G数等の表示
            # if ART == 0:
            #     print(i, "G, BB, ", Total, "枚, DZ", DZ, "G, DT:", DT, "G")
            # elif ART == 1:
            #     print(i, "G, BB(ART), ", Total, "枚, DZ", DZ, "G, DT:", DT, "G")
    
            # ART獲得したらART状態に移行する
            if DZ + DT > 0:
                ART = 1
    
        # 異色BBの時
        elif 異色BB範囲_下 <= rand <= 異色BB範囲_上:
            # ボーナス察知で次Gに1.5枚消費
            Total = Total - 1.5
            Invest = Invest + 1.5
    
            # 異色BB関数を呼んで結果を受け取る
            IBBResult = IBB(ART, Total, DT)
            Total = IBBResult[0]
            DT = IBBResult[1]
    
            # 当選G数等の表示
            # if ART == 0:
            #     print(i, "G, 異色BB, ", Total, "枚, DZ", DZ, "G, DT:", DT, "G")
            # elif ART == 1:
            #     print(i, "G, 異色BB(ART), ", Total, "枚, DZ", DZ, "G, DT:", DT, "G")
    
            # ART獲得したらART状態に移行する
            if DZ + DT > 0:
                ART = 1
    
        # RBの時
        elif REG範囲_下 <= rand <= REG範囲_上:
            # ボーナス察知で次Gに1.5枚消費
            Total = Total - 1.5
            Invest = Invest + 1.5
    
            # RB関数を呼んで結果を受け取る
            RBResult = RB(ART, Total, DT)
            Total = RBResult[0]
            DT = RBResult[1]
    
            # 当選G数等の表示
            # if ART == 0:
            #     print(i, "G, RB, ", Total, "枚, DZ", DZ, "G, DT:", DT, "G")
            # elif ART == 1:
            #     print(i, "G, RB(ART), ", Total, "枚, DZ", DZ, "G, DT:", DT, "G")
    
        # リプレイの時
        elif リプレイ範囲_下 <= rand <= リプレイ範囲_上:
            Total = Total + 3
    
        # 三択9枚役の時
        elif 三択9枚役範囲_下 <= rand <= 三択9枚役範囲_上:
            # ART中は毎回取得
            if ART == 1:
                Total = Total + 9
            # 通常時は1/3で取得
            elif ART == 0:
                if random.randint(1, 3) == 1:
                    Total = Total + 9
    
        # 共通9枚役の時
        elif 共通9枚役範囲_下 <= rand <= 共通9枚役範囲_上:
            Total = Total + 9
    
        # チェリーの時
        elif チェリー範囲_下 <= rand <= チェリー範囲_上:
            Total = Total + 2
    
        # スイカの時
        elif スイカ範囲_下 <= rand <= スイカ範囲_上:
            Total = Total + 8
    
        # ART中リプレイの時
        elif ART中リプレイ範囲_下 <= rand <= ART中リプレイ範囲_上:
            # ART中のみ取得
            if ART == 1:
                Total = Total + 3
    
        # パンク1枚役の時
        elif パンク1枚役範囲_下 <= rand <= パンク1枚役範囲_上:
            # ART中のパンク役は回避する
            if ART == 1:
                Total = Total
    
        return ART, Total, DZ, DT, Invest
    
    if __name__ == "__main__":
        # 試行条件の設定
        # ビタ押し成功率[%]
        Bita = 80
        # 試行回数
        loop = 50000000
    
        # 結果を入れる箱の準備
        Slump = [] # 1G毎の差枚を入力
        Total = 0   # 現在の差枚を入力
        Invest = 0  # 投入枚数を入力
    
        # ループ処理の準備
        DZ = 0  # DZのG数を入力
        DT = 0  # DTのG数を入力
        ART = 0    # ARTフラグ(1:ART中、0:通常時)
        Limit = 1   # ARTの連続G数を入力(1500Gで完走させる)
        i = 1   # 総回転数を入力
    
        # ループ処理
        while i <= loop:
            # 1回転あたり3枚使用
            Total = Total - 3
            Invest = Invest + 3
    
            # 乱数の取得
            rand = random.randint(1, 65536)
    
            # 当否判定処理
            # 通常時の処理
            if ART == 0:
                # 抽選結果を取得
                Result = Normal(rand, ART, Total, DZ, DT, Invest, Bita)
    
                # 各数値を抽選結果に更新
                ART = Result[0]
                Total = Result[1]
                DZ = Result[2]
                DT = Result[3]
                Invest = Result[4]
    
                Slump.append(Total)
    
            elif ART ==1:
                # ART回数が0になるまでループ
                while DZ + DT > 0:
                    # 1回転あたり3枚使用
                    Total = Total - 3
                    Invest = Invest + 3
    
                    # 乱数の取得
                    rand = random.randint(1, 65536)
    
                    # 抽選結果を取得
                    Result = Normal(rand, ART, Total, DZ, DT, Invest, Bita)
    
                    # 各数値を抽選結果に更新
                    ART = Result[0]
                    Total = Result[1]
                    DZ = Result[2]
                    DT = Result[3]
                    Invest = Result[4]
    
                    Slump.append(Total)
    
                    # ART残回数減算処理
                    # DTから消化する
                    if DT > 0:
                        DT = DT - 1
                    else:
                        DZ = DZ - 1
    
                    # ARTの残G数がなくなるか、完走でARTを抜ける
                    if DT == 0 and DZ == 0:
                        ART = 0
                        Limit = 0
                    elif Limit >= 1500:
                        ART = 0
                        Limit = 0
                        print("完走")
    
                    # ART中も総回転数に加算
                    i = i + 1
    
                    # ARTの連続G数を加算
                    Limit = Limit + 1
    
            # 総回転数を加算
            i = i + 1
    
        # 結果の表示
        pylab.title("出玉率:" + str(round(((Total + Invest) / Invest * 100), 1)) + "[%], " + "ビタ成功率:" + str(Bita) + "[%]", fontname="MS Gothic")
        pylab.plot(Slump)
        pylab.xlabel("回転数[回]", fontname="MS Gothic")
        pylab.ylabel("差枚数[枚]", fontname="MS Gothic")
    
        pylab.show()

5. 結果の確認

ということでシミュレータを作成したらやることは一つですね!
ビタ押し成功率ごとの出玉率(機械割)を算出してみました。

ビタ成功率 0 10 20 30 40 50 60 70 80 90 100
出玉率(機械割) 94.5% 95.3% 96.5% 97.2% 98.1% 99.0% 99.8% 100.5% 101.4% 102.1% 102.9%
※算出条件
通常・ART込みで5000万G
チェリー・スイカ100%取得
1枚役は取得しない
ボーナス判別に1.5枚使用

ビタ100%の出率は問題なさそうですが、ビタ52%の出率はちょっと低めに出てそうですね。
もしかしたらビタ失敗時に救済された際の上乗せG数が多めに設定されているのかもしれません。

ということで、救済時だけ上乗せG数の振分を優遇してみました。
結果はこちら。

ビタ成功率 0 10 20 30 40 50 60 70 80 90 100
出玉率(機械割) 96.8% 97.6% 98.0% 98.7% 99.2% 99.9% 100.5% 101.0% 101.7% 102.3% 102.8%
※算出条件
ビタ成功時よりも救済時の上乗せを優遇

これだと巷に出回っている情報と一致しますね。
やはり、救済時の上乗せは優遇されていそうです。
ちなみに、ざっくりですがビタ成功時の上乗せ期待値を5.6[G/回]、救済時の上乗せ期待値を8.4[G/回]にすると出玉率がいい感じになりました。

せっかくなので、もう一つプログラムをいじって遊んでみます。
1年間土日にディスク稼働するとどうなるか!
ざっくりですが、1年間土日が100日、1日5000G回すとして、計50万Gを100人分シミュレートしてみます。
ビタ成功率は、70~100%まで10%刻みで結果を見てみます。
結果はこちら。

ビタ成功率 70 80 90 100
勝率 71% 81% 94% 99%

ちなみに各ビタ成功率でのスランプグラフはこんな感じ。




サンプル人数が少ないので何ともたまたまかもしれませんが、ビタ率≒勝率って感じですかね。
にしても、どのビタ率でも1番勝った人と負けた人で10万枚くらいの差があるのは驚きです。
ディスクは荒いって言われますが、本当にその通りですね。

という感じでちょっとコードをいじると色々遊べるのでぜひ色々試してみてください。


にほんブログ村 スロットブログ スロット情報へ
にほんブログ村

コメント

このブログの人気の投稿

【WEBアプリ】Sキングハナハナ-30のベル確率予想&ベル確率逆算ツール&設定判別ツール

【WEBアプリ】ハナハナホウオウ天翔のベル確率を差枚数から逆算するツール

【WEBアプリ】ハナハナホウオウ天翔の設定判別ツール