# [Miner Gun Builder](https://hackmd.io/@6NWpke4BRK68dykzV2EFnQ/B1nOHR6EF)の検証 ## Critical x 2 |アイコン| 名前 | 説明 | | -- | -------- | -------- | |![](https://i.imgur.com/r3MnaLk.png) | Critical x 2 | A chance of 33% to double the damage of tha passing projectile | ### 経緯 一部のサイトで、Critical x 2の効果を66%ダメージ増と説明しているのを見かけた。 念の為検証する。 ### 検証方法 - Challenge ModeをONにすることで、CaptainやSkillでの底上げを無効にする。 - Critical x 2のみ搭載する ![](https://i.imgur.com/jZuxLKl.png) - Stage17を開始し。開始直後に前方に加速。これを数十回繰り返す。 繰り返しの都度Highest projectile damage(最大ダメージ)と、Projectiles Ejected(発射数)を記録。 Projectiles Ejectedは3もしくは4になるはず。 - Projectiles Ejected(A)の3,4それぞれで、最大ダメージが1、つまりCriticalが効かなかった場合、の数(B)と繰り返しの数(C)をだす。 - 方程式を解いて、Critical x 2が発動する確率xを求める。 $${(1-x)^A=\frac{B}{C}}$$ - 例 |Projectiles Ejected|Highest Damage|回数| |-|-|-| |3|1|9| |3|2|23| |4|1|7| |4|2|23| この時、Projectiles Ejected=3について下記が成り立つ。 $${(1-x)^3=9/23 (0<x<1)}$$ $${x=-\frac{ \sqrt[3]{2}\times3^\frac{2}{3} }{4}+1}$$ $${x\risingdotseq0.344814651}$$ Projectiles Ejected=4について下記が成り立つ $${(1-x)^4=7/30 (0<x<1)}$$ $${x=-\frac{\sqrt[4]{189000}}{30}+1}$$ $${x\risingdotseq0.30498497}$$ ### 検証結果 Criticalx2が発動する確率は66%よりも33%に近い。 ### 補足 方程式は[Microsoft数学ソルバー](https://play.google.com/store/apps/details?id=com.microsoft.math&hl=ja&gl=US)で解いた。 ## Critical x 10 同様に求めるとCritical x 10の発動する確率はおよそ4%だった。 ###### tags: Miner Gun Builder ## Charge ![](https://i.imgur.com/IMFWJf9.png) ### 経緯 ゲーム中の説明には >Adds 20% of its damage to following projectiles. とあるが、他の画面の説明には > 20% of each passing projectiles damage is added to the damage pool of the item. Every projectile will receive 10% of this damage pool to its damage. This results in a damage pool that increases till 20% of the added damage equals roughly 10% of the outgoing damage. It will smooth out damage spikes over multiple projectiles. A strong projectile passes its damage to the following projectiles till the damage spike in the damage pool is used up and euilibrium is reached again > (Deepl日本語訳) 通過する各投射物のダメージの20%がアイテムのダメージプールに追加される。すべての投射物は、このダメージプールの10%のダメージを受けます。 この結果、追加されたダメージの20%が発射されたダメージの約10%に相当するまで、ダメージプールが増加します。これにより、複数の投射物のダメージスパイクをスムーズにすることができます。 強力な投射物は、ダメージプールのダメージスパイクが使い切られて再び均衡状態になるまで、そのダメージを次の投射物に渡します。 と有る。この2つの説明の関係が不明。検証する。 ### プログラムでの検証 Rubyのプログラムを作り検証した。 ```ruby= # 入力projectile毎のダメージ d1 = 1000.0 d2 = 100.0 ary = [d1,d2] # damage1000,1000の2つのprojectileが入力 pool_damage = 0.0 1000.times{ total_out_damage = 0.0 ary.each{|projectile_damage_in| pool_damage += 0.2 * projectile_damage_in total_out_damage += projectile_damage_in + 0.1 * pool_damage pool_damage = pool_damage * 0.9 } puts sprintf("%5.3f",total_out_damage) #出力ダメージ } ``` その結果とゲームの実行結果が一致したため、下記が言える。 - アイテムはダメージを出し入れするpoolを持っている - 通過するprojectileのダメージの20%をコピーしpoolに蓄える - この際、projectileのダメージは減らない - 通過するprojectileにpoolの10%のダメージを与える - この際、poolからその分ダメージが減る さらにプログラムの実行から、Projectileとpoolの間のダメージのコピー/受け渡しは最初は増減し定まらないものの、いずれ平衡状態となることが確認できた。 平衡状態でのChargeアイテムからのprojectileの出力ダメージは計算でも求まる。 - 入力projectileのダメージを $$D_{in}$$ - 出力projectileのダメージを$$D_{out}$$ - projectile入力直前のpoolの蓄えるダメージを $$P_{1}$$ - projectile出力時点のpoolの蓄えるダメージを$$P_{2}$$ とすると、poolの蓄えるダメージのprojectileの入力/出力時の変化は前述の内容から下記。 $$P_{2}=P_{1}+0.2D_{in}$$ 平衡状態ではpoolへの入力と出力が一致するので下記が成り立つ。 $$0.2D_{in}=0.1P_{2}$$ この2つから、 $$P_{2}=2D_{1}$$ これをprojectile出力時点のダメージを表す下記の式に代入。 $$D_{out}=D_{in}+0.1P_{2}$$ すると、 $$D_{out}=1.2D_{in}$$ よってChargeを用いると後続のダメージが20%増加するので、経緯に挙げたどちらの説明も正しい。 最初は増減するがいずれ出力ダメージは入力ダメージの20%増加に落ち着く。 なおprojectileが1つでも複数でも同じ。 ## Adds an additional projectileで追加されるprojectileのダメージは幾つになるのか ### 検証 ![](https://i.imgur.com/8YWnP1d.png) Damage+100の後に、Adds an additional projectileを置く。 結果、lowest projectile damageはHighest projectile damageと同じ101だった。 ![](https://i.imgur.com/tZZQM1Z.png) ### 結論 Adds an additional projectileへの入力projectileの平均/ランダムに選んだprojectileから取得 など、Adds an additional projectileへの入力projectileから求めている。 具体的な決定方法は不明だが、いずれにせよ、base damageではない。 ## legendaryのTier damageの10%の計算は四捨五入? - 結果 YES。四捨五入。 ## legendaryのMore when lowerは、ダメージが一様なら増えない? YES ## legendaryのMore when lowerとCritical系を組み合わせた場合の最小/平均/最大ダメージは、何倍になるか ### 検証 ```ruby= base_damage = 1.0 def generate(base_damage) yield base_damage end def critical2(damage) if rand(100) < 33 damage * 2 else damage end end def critical10(damage) if rand(100) < 4 damage * 10 else damage end end def critical_random(damage) case rand(13) when 0 0.0 * damage when 1,2,3,4,5,6,7,8,9 1.0 * damage when 10 2.0 * damage when 11 3.0 * damage when 12 4.0 * damage else raise StandardError.new end end class MoreThanLower def initialize @last_damage = nil end def proc(damage) if @last_damage if @last_damage > damage @last_damage = damage * 4 else @last_damage = damage end else @last_damage = damage end @last_damage end end max_damage = 0 min_damage = nil last_damage = nil obj = MoreThanLower.new total_damage = 0.0 i = 0 10000000.times{ generate(base_damage){|damage| #damage = obj.proc(critical2(damage)) #damage = obj.proc(critical10(damage)) damage = obj.proc(critical_random(damage)) max_damage = damage > max_damage ? damage : max_damage min_damage = (min_damage == nil || damage < min_damage) ? damage : min_damage total_damage += damage i += 1 } } puts "min:" + min_damage.to_s puts "avg:" + (total_damage/i).to_s puts "max:" + max_damage.to_s ``` ### 結果 |item|最小ダメージ|平均ダメージ|最大ダメージ| |-|-|-|-| |Critical x2|1倍|5.32倍(Critical x2単独の1.33の4倍)|8倍(Critical x2単独の4倍)| |critical x10|1倍|4.24倍(Critical x10単独の3.12倍)|10倍(Critical x10単独の1倍)| |Random critical|0倍|3.88倍(Random Critical単独の1.38の2.8倍)|16倍(Random critical単独の4.12倍)| ## Slow damage ![](https://i.imgur.com/inkYl7R.png) - Itemの効果 More damage, x2 at 1 speed to x5 at 0.2 speed, for slower projectiles. - 検証 Damageの加算は、item通過時点と、eject時点の、どちらで行われる? - 結果 Item通過時点ではなくeject時点のspeedで倍率を計算する。