裏CHUNSOFT > ROMイメージ改造・解析 > ダメージ計算式
ダメージ計算式
とにかく式だけ知りたい方へ
ダメージ計算式は以下の通りです。
(ダメージ)=(攻撃力)*(112〜143)*(15/16)^(防御力)/128
但し、15/16は乗じる度に切り上げ、/128は切り捨て。
計算過程を詳しく知りたい方へ
攻撃力の取得からダメージ計算までのルーチンの逆アセンブルリストです。 これを見ながら解説していきます。 数値は全て16進数です。 $XXはメモリ(変数)を表します。 ダメージ計算に影響しない命令にはコメントを付けていません。 1つ1つ解説するまでもない命令は、複数の命令をまとめて1つのコメントで解説しています。
021527 BF 7D 86 7E LDA $7E867D+"X" ; "A" = (攻撃力) 02152B 85 02 STA $02 ; $02 = "A" 02152D 84 00 STY $00 ; 02152F 86 01 STX $01 ; 021531 DA PHX ; 021532 22 EF 28 C2 JSR $C228EF ; 下のルーチンへ
$02に攻撃力を代入します。 ここは問題ないでしょう。
0228EF 08 PHP ; 0228F0 E2 30 SEP #$30 ; 0228F2 A9 7E LDA #$7E ; 0228F4 48 PHA ; 0228F5 AB PLB ; 0228F6 A4 00 LDY $00 ; 0228F8 A6 01 LDX $01 ; 0228FA A5 02 LDA $02 ; "A" = $02 0228FC 48 PHA ; "A"の値をプッシュ 0228FD 22 5F F6 C3 JSR $C3F65F ; $00 = (乱数) (乱数生成ルーチン) 022901 A5 00 LDA $00 ; "A" = $00 022903 29 1F AND #$1F ; "A" = 00〜1F 022905 18 CLC ; 022906 69 70 ADC #$70 ; "A" += 70 022908 85 00 STA $00 ; $00 = "A" 02290A 68 PLA ; プッシュしていた値を"A"に代入 02290B 85 01 STA $01 ; $01 = "A" 02290D 22 CB E3 C3 JSR $C3E3CB ; 下のルーチンへ
$00に乱数で00h〜1Fhの値を代入し、それに70hを加えます。 これで、$00は70h〜8Fh(112〜143)の値をとります。 これはダメージのランダム変化に使用されます。 すなわち、ダメージのランダム変化は32段階です。
また、攻撃力の値が$01に代入されました。
03E3CB 08 PHP ; 03E3CC E2 20 SEP #$20 ; 03E3CE A5 01 LDA $01 ; "A" = $01 03E3D0 49 FF EOR #$FF ; "A" = "A" xor FF 03E3D2 EB XBA ; 03E3D3 A9 00 LDA #$00 ; "A" = NN00 (NN = "A" xor FF) 03E3D5 85 01 STA $01 ; $01 = "A" 03E3D7 C2 20 REP #$20 ; 03E3D9 0A ASL ; "A" *= 2 (を10000で割った余り) 03E3DA B0 02 BCS $E3DE ; 03E3DC 65 00 ADC $00 ; 上の演算で"A"が10000を超えなければ"A" += $00 (中略) ; 上3行の処理を計8回繰り返す 03E401 85 00 STA $00 ; $00 = "A" 03E403 28 PLP ; 03E404 6B RTL ; 下のルーチンへ
"A"を2倍して、それが10000hを超えなければ"A"に$00を加えるという処理を8回も繰り返しています。 一見訳の分からないことをしているように見えますが、落ち着いて考えてみましょう。
$00は最大でも8Fhですから、この繰り返しが行われる前の"A"の上位8ビット(NNの部分)が$00の加算により変化することはありません。 そして、加算された$00もその後一緒に2倍されていきますから、この処理は次のように言い換えることができます。
(新しい値)=0
"A"のbit15が0ならば(新しい値)+=$00*80h
"A"のbit14が0ならば(新しい値)+=$00*40h
"A"のbit13が0ならば(新しい値)+=$00*20h
"A"のbit12が0ならば(新しい値)+=$00*10h
"A"のbit11が0ならば(新しい値)+=$00*08h
"A"のbit10が0ならば(新しい値)+=$00*04h
"A"のbit9が0ならば(新しい値)+=$00*02h
"A"のbit8が0ならば(新しい値)+=$00
$00=(新しい値)
ところで、"A"のbit8〜15は03E3D0hでxorされた値なので、攻撃力のbit0〜7とはそれぞれのビットが互いに違う関係にあります。 なので、"A"のbit8〜15を攻撃力のbit0〜7に置き換えると、次のようになります。
(新しい値)=0
攻撃力のbit7が1ならば(新しい値)+=$00*80h
攻撃力のbit6が1ならば(新しい値)+=$00*40h
攻撃力のbit5が1ならば(新しい値)+=$00*20h
攻撃力のbit4が1ならば(新しい値)+=$00*10h
攻撃力のbit3が1ならば(新しい値)+=$00*08h
攻撃力のbit2が1ならば(新しい値)+=$00*04h
攻撃力のbit1が1ならば(新しい値)+=$00*02h
攻撃力のbit0が1ならば(新しい値)+=$00
$00=(新しい値)
つまりこの処理は何の難しいこともない、(攻撃力)*$00を求める処理だったのです。 そして、$00の値は(攻撃力)*$00に変わります。
022911 C2 20 REP #$20 ; 022913 DA PHX ; 022914 BE 91 86 LDX $8691+"Y" ; "X" = (防御力) 022917 80 0F BRA $2928 ; 022928へジャンプ 022919 A5 00 LDA $00 ; "A" = $00 02291B 4A LSR * 4 ; "A" /= 10 (余りは切り捨て) 02291F 49 FF FF EOR #$FFFF ; "A" = "A" xor FFFF 022922 38 SEC ; 022923 65 00 ADC $00 ; "A" += $00 + 1 (を10000で割った余り) 022925 85 00 STA $00 ; $00 = "A" 022927 CA DEX ; "X" -- 022928 D0 EF BNE $2919 ; "X" != 0のとき022919へジャンプ 02292A FA PLX ; 02292B A5 00 LDA $00 ; "A" = $00 02292D 0A ASL ; "A" *= 2 (を10000で割った余り) 02292E 90 03 BCC $2933 ; 022930 A9 00 FF LDA #$FF00 ; 上の処理で"A"が10000を超えると"A" = FF00 022933 E2 20 SEP #$20 ; 022935 EB XBA ; "A"の上位8バイトと下位8バイトを交換(交換された後の下位8バイトがダメージになる) 022936 48 PHA ;
いよいよダメージ計算です。 "X"は防御力ですから、防御力の値だけ次の処理を繰り返していることが分かります。
"A" = $00 "A" /= 10 "A" = "A" xor FFFF "A" += $00 + 1 $00 = "A"
この処理を1つの式にまとめると次のようになります(数値は10進数)。
$00(新)=(($00/16) xor 65535)+$00+1
パッと見ただけでは$00はどうなるのか分かりませんね。 しかし、($00/16) xor 65535は、65535-$00/16と同じですから、この式を次ように変更しても同じです。
$00(新)=65535-$00/16(切り捨て)+$00+1=$00*15/16(切り上げ)+65536
これを65536で割った余りが新しい$00になりますから、$00(新)=$00*15/16、つまり防御力1につき$00に15/16を乗じるということです。
後は簡単です。 "A"に$00を代入して2倍し、その上位8バイト、すなわち256で割った値がダメージになります。 式で表すと、
(ダメージ)=$00*(15/16)^(防御力)*2/256=(攻撃力)*(112〜143)*(15/16)^(防御力)/128
但し、15/16は乗じる度に切り上げ、/128は切り捨て。
となります。 022930hはダメージが255を超えた場合に255にする処理です。
2009年2月25日更新
裏CHUNSOFT > ROMイメージ改造・解析 > ダメージ計算式