モンクDPS予想4

以前の日記で、モンクがブロー系チェインを付けたときの与ダメ予想プログラムを載せたけれど、そのときはまだ武器は訓練用の武器専用だった。今日は一般の武器でも予想できるようにプログラムを書き換えてみた。こんな感じ。

N=10000                  # 実験回数

FB=0.45*(1.21+0.05)      # FB発動率
BB=0.05*(1.21+0.05)      # BB発動率
FnB=0.05*(1.21+0.05)     # FnB発動率


AT_N  = 363..378         # 通常攻撃与ダメ
N_ADD = 19               # 通常物理攻撃上昇
AT_FB = 595..615         # FB与ダメ
AT_BB = 1008..1042       # BB与ダメ
AT_FnB= 1906..1971       # FnB与ダメ

R_UP  = 0.35+0.02        # リアクションスキルダメージ増
F_UP  = 0.10             # 最終ダメ増
D_Nat = 0.15             # 自然ダメ増

ST_N  = (2+1)*1.3*1.3    # 通常スタ攻
ST_FB = (4+1)*1.3        # FBスタ攻
ST_BB = (6+1)*1.3        # BBスタ攻
ST_FnB= (8+1)*1.3        # FnBスタ攻

TM_N  = 1.04             # 通常攻撃の時間
TM_FB = 0.53             # FBの時間
TM_BB = 0.53             # BBの時間
TM_FnB= 0.53             # FnBの時間

CT_FnB= 5*0.8            # FnBのCT

CRI=0.8                  # クリ率
CRI_DM=1.5+1.0+0.07      # クリダメ増
GRO_DM=1.0+1.2           # グロダメ増

MaxStamina = 280         # かかしの最大スタミナ

AT_Hash={:normal => AT_N, :fb => AT_FB, :bb => AT_BB, :fnb => AT_FnB}
ST_Hash={:normal => ST_N, :fb => ST_FB, :bb => ST_BB, :fnb => ST_FnB}
TM_Hash={:normal => TM_N, :fb => TM_FB, :bb => TM_BB, :fnb => TM_FnB}

$frand=Random.new()
def occ(q)
  $frand.rand(1.0) < q
end

# 攻撃の種類を決める
def at_type(prev, time, fnb_ct)
  fnb = time >= fnb_ct    # FnBのCTが終わっているか
  case prev
  when :normal
    return :fnb if fnb && occ(FnB)
    return :bb if occ(BB)
    return :fb if occ(FB)
  when :fb
    return :fnb if fnb && occ(FnB)
    return :bb if occ(BB+0.45)
    return :fb if occ(FB)
  when :bb
    return :fnb if fnb && occ(FnB+0.30)
    return :fb if occ(FB)
  when :fnb
    return :bb if occ(BB)
    return :fb if occ(FB)
  end
  return :normal
end

def attack (type)
  rand AT_Hash[type]
end

def sim (max_time)
  type=:start
  stamina=MaxStamina
  gro_time=0
  time=0
  total=0
  fnb_ct=0
  
  while time < max_time
    type=at_type(type, time, fnb_ct)

    fnb_ct = time+CT_FnB if type==:fnb
    at = attack(type)
    dm = type == :normal ? at+N_ADD : at*(1.0+R_UP)

    dm *= CRI_DM if occ(CRI)

    if time <= gro_time then   # グロ中
      dm *= GRO_DM
    else                       # グロ中でない
      stamina -= ST_Hash[type]
    end

    dm *= (1.0+F_UP)

    total +=dm.to_i
    time  +=TM_Hash[type]

    if stamina < 0 then
      stamina = MaxStamina
      gro_time = time + 5      # 5秒間グロ
    end
  end
  total
end

N.times do
  p sim(2*60)
end

このプログラムの正しさの検証はまた後日。