【黒い砂漠】レブラスで貯めるスタック価格をシミュレートしてみた

スポンサーリンク

どうも、TeXTeXです。
黒い砂漠ですが確率表記&新取引所が実装されたのでレブラス+15チャレンジで貯めるスタックの価格を計算してみました。
実際は計算というよりゴリ押しシミュレートなんですがね…
細けえこたぁってやつです。

 

ついでに前回の記事でスタック貯め成功率を計算できますのでよろしければご利用下さい。

 

スタックコストデータ

とにもかくにもまずは結果のデータから御覧ください。

[table id=15 /]

このコストですが、おそらく50くらいまではレブラス叩きが最安となるためそこまではおおよその参考にして下さって結構です。
しかし50~60の間くらいで緑防具真Ⅳチャレンジと交差すると思われるので、50を超えたあたりからは参考にならない数値となってきます。
その辺の計算は現在やってる最中なのでそのうちブログ更新できるかなと思ってます。(と言っても取引所の黒石関連が青天井になるという噂もあるのでそれ以降になりそうですが)

さて、スタック50にかかる費用ですがおよそ166Mシルバーと計算されました。価格としてはジャスティンアーマーが買える価格なので、このあたりで+15が成功してしまうと精神的にきつそうです。さらに必要ブラックストーン数も約750個となっており1日100個集められたとしても1週間で貯めきれない数が要求されます。これだとちょっとコスト的にも物量的にも厳しいです。
そこでブラックストーン100個を目安にすると、スタック32が101.4個でコストは22.4Mシルバーと現実的な数値になってきます。これくらいなら挑戦しても良さそうですが、抽出する場合を考えると83.73個で184Mシルバーなスタック30が良いでしょうね。まあどのあたりを目標にするかはブラックストーン供給数と資産との相談となります。でもナーガ2時間(武器防具考慮せず)で貯められそうなスタック30近辺は非常に魅力的です。
しかしこれはあくまで期待値なので、試行回数が少なければハマることも上手くいくこともあります。なのでどこまで叩くかというのは流れを読む必要がありそうです。つまりどこまで参考にするかは自己責任でお願いします。

ソイソースコード

ここからはシミュレートしたソースコードを書いていきます。言語はPython 3です。
ちなみにPythonを触るのは初めてですし、プログラミングも別に得意ではないのでガバガバです。
スタックコストを求める方は半日以上かかりました。やっぱりスタック80まで計算したのが馬鹿でしたね。裏で砂漠起動してたのもアホなんですけど…

まずはコストを求める方から。
※16スレッドのCPUを想定してます。

from multiprocessing import Pool
import random
import time
import csv

BLACK_STONE_COST = 210000
DURABILITY_COST = 6450
CLEANSE_COST = 100000
PROCESSER_NUM = 12
INITIAL_COST = 0
INITIAL_STACK = 0
INITIAL_P = 0.02
STEP_P = 0.002

NUMBER_OF_RUNS = 1000000
TARGET_STACK = 80

def stack_simulate(total_cost,stack,target_stack):
    while stack < target_stack:
        total_cost += BLACK_STONE_COST
        if random.random() < (INITIAL_P + (STEP_P * stack)):
            #Enhance successful
            total_cost += CLEANSE_COST
            stack = 0
        else:
            #Enhance failed
            total_cost += DURABILITY_COST
            stack += 1
    return total_cost

def wrap(List):
    return stack_simulate(*List)
    
def malti_process(target_stack):
    total_cost = INITIAL_COST
    stack = INITIAL_STACK
    List = [(total_cost,stack,target_stack) for runs in range(NUMBER_OF_RUNS)]
    pool = Pool(processes=PROCESSER_NUM)
    total_cost = pool.map(wrap,List)
    pool.close()
    return total_cost

def first(target_stack,f):
    n = 0
    cost = 0
    total_cost = malti_process(target_stack)
    for n in range(NUMBER_OF_RUNS):
        cost = cost + total_cost[n]
    writer = csv.writer(f)
    writer.writerow([target_stack, cost/NUMBER_OF_RUNS])
    

if __name__ == "__main__":
    start = time.time()
    with open('stack_cost_(0-80).csv', 'w', newline = '') as f:
        for target_stack in range(1,TARGET_STACK + 1):
            first(target_stack,f)
            print(target_stack,'done\n')
    f.close()
    elapsed_time = time.time() - start
    print ("elapsed_time:{0}".format(elapsed_time) + "[sec]")

 

お次はブラックストーン数の方。

from multiprocessing import Pool
import random
import time
import csv

BLACK_STONE_COST = 210000
DURABILITY_COST = 6450
CLEANSE_COST = 100000
PROCESSER_NUM = 12
INITIAL_COST = 0
INITIAL_STACK = 0
INITIAL_P = 0.02
STEP_P = 0.002

NUMBER_OF_RUNS = 1000000
TARGET_STACK = 50

def stack_simulate(total_num,stack,target_stack):
    while stack < target_stack:
        total_num +=1
        if random.random() < (INITIAL_P + (STEP_P * stack)):
            #Enhance successful
            stack = 0
        else:
            #Enhance failed
            stack += 1
    return total_num

def wrap(List):
    return stack_simulate(*List)
    
def malti_process(target_stack):
    total_num = 0
    stack = INITIAL_STACK
    List = [(total_num,stack,target_stack) for runs in range(NUMBER_OF_RUNS)]
    pool = Pool(processes=PROCESSER_NUM)
    total_num = pool.map(wrap,List)
    pool.close()
    return total_num

def first(target_stack,f):
    n = 0
    num = 0
    total_num = malti_process(target_stack)
    for n in range(NUMBER_OF_RUNS):
        num = num + total_num[n]
    writer = csv.writer(f)
    writer.writerow([target_stack, num/NUMBER_OF_RUNS])
    

if __name__ == "__main__":
    start = time.time()
    with open('stack_num_(0-50).csv', 'w', newline = '') as f:
        for target_stack in range(1,TARGET_STACK + 1):
            first(target_stack,f)
            print(target_stack,'done\n')
    f.close()
    elapsed_time = time.time() - start
    print ("elapsed_time:{0}".format(elapsed_time) + "[sec]")

※2つに分けてるのは後からBS数を計算したためです。普通にやるなら2つ合体させちゃってOKです。

 

参考にしたのは某巨大掲示板の書き込み。

413名も無き冒険者 (ワッチョイ XXXX-XXXX [XXX.XXX.XXX.XX])2019/01/13(日) 22:25:59.35ID:b5mqneyv0
>>411
すまそ。

 

import random
BLACK_STONE_COST = 210000
DURABILITY_COST = 6450
CLEANSE_COST = 100000

 

NUMBER_OF_RUNS = 1000000
TARGET_STACK = 15

 

total_cost = 0
runs = 0

 

while runs < NUMBER_OF_RUNS:
stack = 0
while stack < TARGET_STACK:
total_cost += BLACK_STONE_COST

 

if random.random() < (0.02 + (0.002 * stack)):
#Enhance successful
total_cost += CLEANSE_COST
stack = 0
else:
#Enhance failed
total_cost += DURABILITY_COST
stack += 1
runs += 1

 

print(round(total_cost/NUMBER_OF_RUNS, 0))
引用 https://mevius.5ch.net/test/read.cgi/mmo/1547208123/
※IPアドレス等は個人情報のためこちらで伏せ字に変更しました。

シングルスレッドで劇遅い&ファイル出力がなかったためそこを含めて何点か改善しました。本当はwhile文もFor文に書き換えたほうが速いんですけど…面倒なのでやめました。
やってることは

  • (メルセンヌ・ツイスタで)0~1の疑似乱数生成
  • 成功率より小さい数なら成功
  • 成功したらスタックを0にして浄化コストを加算
  • 失敗したらスタックに1加算して修理コストを加算
  • スタックが目標スタックに達したら終了
  • 総コストを保存しておく
  • これを各スタック100万回繰り返す

だけです。マシンパワーでゴリ押しですね。こういうとき多コアは強いです。
お次はこの式から応用を利かせて、高スタックの場合や真装備強化のコストやアクセ必要数を厳密に計算してみたいですね。そのためにも早く新取引所の仕様をしっかりと決めてもらいたいものです。

 

コメント

タイトルとURLをコピーしました