TOP > プログラミング関係解説&調査 > 命中判定について

命中判定について

ダメージ計算式の解説戦闘用乱数計算では、単発ダメージ量+乱数でのブレについて説明した。
実際には、その前に「技が命中するかどうか」の判定が行われている。
ここでは、命中判定についての解説と、少しばかりおまけも紹介する。

命中判定方法については、既に世界の合言葉は森部様にあるので、計算方法だけ知りたい場合はこれで充分である。

 ・攻撃の命中判定:
LV+技LV>=(0~(敵LV-1))のとき命中

この判定式は、もちろん、「必中する状況以外の時」に適用される。
必中する状況は、以下の時である。

  1. 攻撃相手が、「マヒ」か「眠り」の状態異常である。
  2. 攻撃相手が、技に設定された「必中状態異常」の時に攻撃する。

1. は広く知られているだろう。
2. だが、これは世界の合言葉は森部様のその他メモに説明がある。

■状態異常中の必中効果

技にはそれぞれ相手がそれぞれ首かため・足かため・腕かためだと必中になるかどうかのフラグがある。
首固めで使用不可になる技もあるように、首固めと腕固めは扱いとしては似たようなもの。

あまり役立つ場面は思いつかないので技データに申し訳程度に。
そもそも、上記の状態異常にするためにはその技を当てる必要があるわけで、それが大変。
他に技を当てる手段としても、LVを下げるか、眠りや麻痺にする選択肢もある。

例えば、「Vシャイン」には、必中状態異常が「腕かため」と設定されている。
つまり攻撃相手が「腕かため」の状態異常の時、「Vシャイン」を使うと、上の命中判定の計算は行われず、必ず命中するということになる。
どの技に設定されているかは、世界の合言葉は森部様の技データの「必中状態異常」の欄で確認できる。

上にもあるとおり、この「必中状態異常」の設定を、実際にゲームをプレイする上でうまく活用できるかどうかと言われると、微妙なところである……。

何はともあれ、以下では実際にプログラム内での命中判定のサブルーチンと、どういう処理をしているのか紹介する。
処理が行われているのは、単発ダメージ量計算より少し前のあたりになる。
戦闘中、敵には0~Fの番号が振られて、どの敵かを区別するようになっているが、以下では便宜上、味方キャラが番号0の敵を攻撃する場合とする。

$C1/D870 LDA $7E901D[$7E:901D]   ;Aに[$7E:901D](技データ13)をロード
$C1/D874 BPL $02    [$D878]      ;ネガティブフラグが立っていないとき[$C1/D878]にジャンプ(回復技判定)
$C1/D878 LDA $7E901C[$7E:901C]   ;Aに[$7E:901C](技データ12)をロード
$C1/D87C LSR A                   ;Aを論理右シフト(/2)
$C1/D87D LSR A                   ;Aを論理右シフト(/2)
$C1/D87E LSR A                   ;Aを論理右シフト(/2)
$C1/D87F LSR A                   ;Aを論理右シフト(/2)
$C1/D880 AND #$07                ;Aと$07の論理積
$C1/D882 AND $7E8F07,x[$7E:AA07] ;Aと[$7E:AA07](敵の状態異常)の論理積
$C1/D886 BNE $27    [$D8AF]      ;ゼロフラグが立っていない時、★[$C1/D8AF]へジャンプ(命中判定を飛ばす)
$C1/D888 LDA $7E8F07,x[$7E:AA07] ;Aに[$7E:AA07](敵の状態異常)をロード
$C1/D88C AND #$30                ;Aと$30(00110000)の論理積(眠り、またはマヒの判定)
$C1/D88E BNE $1F    [$D8AF]      ;ゼロフラグが立っていないとき★[$C1/D8AF]分岐(命中判定を飛ばす)
$C1/D890 JSR $6150  [$C1:6150]   ;乱数計算サブルーチン[$C1:6150]へジャンプ
;
$C1/6150 PHX                     ;乱数計算サブルーチンここから開始
$C1/6151 PHB                     ;↓
$C1/6152 LDA #$00                ;↓
$C1/6154 PHA                     ;↓
$C1/6155 PLB                     ;↓
$C1/6156 LDA $38    [$00:0338]   ;↓
$C1/6158 ORA $39    [$00:0339]   ;↓
$C1/615A ORA $3A    [$00:033A]   ;↓
$C1/615C ORA $3B    [$00:033B]   ;↓
$C1/615E BNE $24    [$6184]      ;↓
$C1/6184 LDX $38    [$00:0338]   ;↓
$C1/6186 STX $4204  [$00:4204]   ;↓
$C1/6189 LDA #$0D                ;↓
$C1/618B STA $4206  [$00:4206]   ;↓
$C1/618E JSR $46C8  [$C1:46C8]   ;↓
;
$C1/46C8 NOP                     ;↓
$C1/46C9 RTS                     ;↓
;
$C1/6191 LDA $39    [$00:0339]   ;↓
$C1/6193 STA $38    [$00:0338]   ;↓
$C1/6195 LDA $3A    [$00:033A]   ;↓
$C1/6197 STA $39    [$00:0339]   ;↓
$C1/6199 LDA $3B    [$00:033B]   ;↓
$C1/619B STA $3A    [$00:033A]   ;↓
$C1/619D LDA $4214  [$00:4214]   ;↓
$C1/61A0 STA $3B    [$00:033B]   ;↓
$C1/61A2 PLB                     ;↓
$C1/61A3 PLX                     ;↓
$C1/61A4 RTS                     ;乱数計算サブルーチンここまで(Aに乱数入る)
;
;符号付8bit x 8bit計算開始
$C1/D893 STA $4202  [$00:4202]   ;A(乱数計算サブルーチンで計算した$00~$FFの乱数)を被乗数としてセット
$C1/D896 LDA $7E900A,x[$7E:AB0A] ;Aに[$7E:AB0A](敵の現在のレベル)をロード
$C1/D89A STA $4203  [$00:4203]   ;A(敵レベル)を乗数としてセット
$C1/D89D NOP                     ;乗算処理待機
$C1/D89E NOP                     ;乗算処理待機
$C1/D89F NOP                     ;乗算処理待機
$C1/D8A0 CLC                     ;キャリーフラグをクリア
$C1/D8A1 LDA $4217  [$00:4217]   ;乗算結果 Aに「乱数×敵レベル」の上位2ビットをロード
$C1/D8A4 CMP $7E900C[$7E:900C]   ;Aと[$7E:900C](「技LV+自LV」)を減算比較
$C1/D8A8 BEQ $05    [$D8AF]      ;ゼロフラグが立っている時[$C1/D8AF]にジャンプ
$C1/D8AA BCC $03    [$D8AF]      ;キャリーフラグが立っていない時[$C1/D8AF]にジャンプ
$C1/D8AC LDA #$00                ;※キャリーフラグなしのジャンプ先、Aに$00をロード
$C1/D8AE RTS                     ;※サブルーチン戻り
$C1/D8AF LDA #$FF                ;★Aに$FFをロード
$C1/D8B1 RTS                     ;サブルーチン戻り
;
$C1/D7F7 BEQ $1C    [$D815]      ;ゼロフラグが立っているとき[$C1/D815]にジャンプ(単発ダメージ量計算をスキップ)
$C1/D7F9 LDA $7E9003,x[$7E:AB03] ;Aに[$7E:AB03]をロード(最終的にヒット数の入るメモリ、初期値0)
$C1/D7FD INC A                   ;Aをインクリメント([$7E:AB03]+1)
$C1/D7FE STA $7E9003,x[$7E:AB03] ;A(=1)を[$7E:AB03]に書き込み(ここで「ヒット数は最低でも1」と設定)
$C1/D802 JSR $D81A  [$C1:D81A]   ;

途中の$C1/6150から$C1/61A4までは、戦闘用乱数計算で紹介した、戦闘用乱数を生成するサブルーチンであるため、説明は省く。
それ以外について順に説明する。

$C1/D870 LDA $7E901D[$7E:901D]   ;Aに[$7E:901D](技データ13)をロード
$C1/D874 BPL $02    [$D878]      ;ネガティブフラグが立っていないとき[$C1/D878]にジャンプ(回復技判定)

最初の2行は、まず攻撃する味方キャラの技の技データ13をAにロードしている。
技データ13の上位2ビットに技のタイプが入っており、対象を回復する技だと、技データ13を2進数で記した時に「10XXXXXX」のように頭に「1」がつく。
入力された数値の最上位ビットが1の時にネガティブフラグが立つので、次のBPL $02は、回復技以外なら[$C1/D878]にジャンプ、という処理になる。
なお、回復技はこの後に命中判定を飛ばすので、必中ということらしい。
要するに、攻撃(または吸収)技のみ命中判定をするという意味での処理である。

$C1/D878 LDA $7E901C[$7E:901C]   ;Aに[$7E:901C](技データ12)をロード
$C1/D87C LSR A                   ;Aを論理右シフト(/2)
$C1/D87D LSR A                   ;Aを論理右シフト(/2)
$C1/D87E LSR A                   ;Aを論理右シフト(/2)
$C1/D87F LSR A                   ;Aを論理右シフト(/2)
$C1/D880 AND #$07                ;Aと$07の論理積
$C1/D882 AND $7E8F07,x[$7E:AA07] ;Aと[$7E:AA07](敵の状態異常)の論理積
$C1/D886 BNE $27    [$D8AF]      ;ゼロフラグが立っていない時、★[$C1/D8AF]へジャンプ(命中判定を飛ばす)

続いて、技データ12をAにロードし、論理右シフトで「÷2」の計算を4回繰り返している。
技データ12だが、先に述べた「必中状態異常」の設定が、上位4ビット(2進数の4文字分、16進数の1文字分)の下3桁分に入っている。
技データ12を2進数「?XYZ????」として見た時に、Xは「腕かため」、Yは「足かため」、Zが「首かため」に対応している、ということになる。
例えば「Vシャイン」の技データ12は「40」であり、2進数では「01000000」であるが、「腕かため」に1が立っているので、「必中状態異常」は「腕かため」である。
「大激怒岩バン割り」だと、技データ12は「52」であり、2進数では「01010010」で、「腕かため」「首かため」が「必中状態異常」ということになる。

2進数だと、÷2することで、8桁の数字が右に移動(シフト)していく。
つまり「÷2」を4回繰り返したことで、技データ12の上位4ビットだけ取り出したことになる。

$C1/D880 AND #$07は、その値と$07(2進数0111)の論理積を取っている。
これで、「必中状態異常」を表す3桁の部分だけが「0XYZ」の形で取り出せる。

次の[$7E:AA07]だが、このメモリには、敵(番号0)の状態異常の状況が記録されている。
オディオモールのダメージ量処理でも紹介したが、16進数2桁(2進数8桁)で、以下のように状態異常が記録されている。
下は例として、眠り状態と毒状態が同時に発生している時(2進法の00101000 = 16進法の$28)を示す。

2進法の位2726252423222120
状態異常石化酔い眠りマヒ腕かため足かため首かため
2進法00101000

ここで下3桁に注目していただきたいのだが、腕かため・足かため・首かための順に状態異常が記録されている。
これは、先程までの計算で取り出した、「必中状態異常」を表す3桁の部分と同じ順序である。
よって、敵の状態異常[$7E:AA07]と、「必中状態異常」を表す3桁の部分の論理積を取った時に、「1」が1個以上立つとしたら、敵の状態異常と、使用技の「必中状態異常」が一致している、ということになる。
最後のBNE $27は、ゼロフラグが立っていない時に[$C1/D8AF]へジャンプしろという命令になるが、[$C1/D8AF]は命中判定を飛ばした位置になる。
つまり、命中判定なしで単発ダメージ量計算に進むということになるから、この時点で命中率100%、必中という扱いになったのである。
なお、[$C1/D8AF]と★を付けたのは、飛び先を示すための印である。

$C1/D888 LDA $7E8F07,x[$7E:AA07] ;Aに[$7E:AA07](敵の状態異常)をロード
$C1/D88C AND #$30                ;Aと$30(00110000)の論理積(眠り、またはマヒの判定)
$C1/D88E BNE $1F    [$D8AF]      ;ゼロフラグが立っていないとき★[$C1/D8AF]分岐(命中判定を飛ばす)
$C1/D890 JSR $6150  [$C1:6150]   ;乱数計算サブルーチン[$C1:6150]へジャンプ

次はもう一度、敵の状態異常の状態である[$7E:AA07]Aにロードしている。
続いてAND #$30で、状態異常の状態と$30の論理積を取っている。
$30は2進数で「00110000」である。
もう一度、状態異常の表を載せる。

2進法の位2726252423222120
状態異常石化酔い眠りマヒ腕かため足かため首かため
2進法00101000

00110000」の「1」の位置は、「眠り」と「マヒ」に当たる。
つまり、敵が「眠り」または「マヒ」の状態異常にあるかどうかの判定をしており、どちらでもなければ論理積の結果は0である。
次のBNE $1Fでは、ゼロフラグが立っていない、つまり敵が「眠り」または「マヒ」なら、[$C1/D8AF]へジャンプしろと指示している。
これも、命中判定なしで単発ダメージ量計算に進む、の意味であり、必中扱いである。

ここまでで、

  • 回復技は必中
  • 技の「必中状態異常」と敵の状態異常が一致していたら必中
  • 敵が「眠り」または「マヒ」なら必中

という、命中判定を必要としない条件の判定を済ませたことになる。

ここから乱数生成のサブルーチン$C1/6150$C1/61A4が開始になる。
つまり、命中判定用の乱数の計算を行う、ということである。
乱数生成の説明は飛ばして、続きについて説明する。
Aには16進数で$00~$FF(10進数で0~255)の乱数が入った状態である。

;符号付8bit x 8bit計算開始
$C1/D893 STA $4202  [$00:4202]   ;A(乱数計算サブルーチンで計算した$00~$FFの乱数)を被乗数としてセット
$C1/D896 LDA $7E900A,x[$7E:AB0A] ;Aに[$7E:AB0A](敵の現在のレベル)をロード
$C1/D89A STA $4203  [$00:4203]   ;A(敵レベル)を乗数としてセット
$C1/D89D NOP                     ;乗算処理待機
$C1/D89E NOP                     ;乗算処理待機
$C1/D89F NOP                     ;乗算処理待機
$C1/D8A0 CLC                     ;キャリーフラグをクリア
$C1/D8A1 LDA $4217  [$00:4217]   ;乗算結果 Aに「乱数×敵レベル」の上位2ビットをロード
$C1/D8A4 CMP $7E900C[$7E:900C]   ;Aと[$7E:900C](「技LV+自LV」)を減算比較
$C1/D8A8 BEQ $05    [$D8AF]      ;ゼロフラグが立っている時[$C1/D8AF]にジャンプ
$C1/D8AA BCC $03    [$D8AF]      ;キャリーフラグが立っていない時[$C1/D8AF]にジャンプ
$C1/D8AC LDA #$00                ;※キャリーフラグなしのジャンプ先、Aに$00をロード
$C1/D8AE RTS                     ;※サブルーチン戻り
$C1/D8AF LDA #$FF                ;★Aに$FFをロード
$C1/D8B1 RTS                     ;サブルーチン戻り

乱数計算後は、掛け算の計算を行っている。
既に述べた符号付8bit x 8bitの計算で、STA $4202で被乗数をセット、STA $4203で乗数をセットすると、被乗数×乗数の結果を$4216$4217に16bitで出力する($4216に答えの上位2バイト、$4217に下位2バイト)。
ここでの掛け算は、「乱数($00~$FF)」×「敵の現在のレベル」である。レベルは戦闘中にバフやデバフで変動するので、現在のレベルを収納している[$7E:AB0A]からロードしている。
LDA $4217では、この掛け算の答えの「上位2ビット」部分だけをロードしている。
例えば、乱数が$70、敵の現在のレベルが$0D(10進数だと13)だったら、$70×$0D = $05B0であるから、「上位2ビット」部分だと、$05である。
そして、下2桁を除き上2桁だけ取り出すというこの作業は、ダメージ計算式の簡易解説などでも紹介した、「小数点を2つ左にずらすということは、162 = 256 = $100で割り算をすることと同じ」である。
よって、LDA $4217Aにロードした値は、10進法なら、

「乱数(0~255)」×「敵の現在のレベル」 / 256

と、いうことになる。
256で割ると

0~「敵の現在のレベル」×255/256

である。

CMP $7E900Cでは、この『0~「敵の現在のレベル」×255/256』と、[$7E:900C]を減算比較している。
[$7E:900C]は、ダメージ計算式の簡易解説の[$7E:900C]の説明にある通り、ダメージ量計算にも使った「技LV+自LV」の値である。
つまり、『0~「敵の現在のレベル」×255/256』と、「技LV+自LV」を減算して比較している。
これより先に処理を見ると、減算の結果、ゼロフラグが立っている、またはキャリーフラグが立っていないなら命中、という判定である。

ゼロフラグが立つのは、
『0~「敵の現在のレベル」×255/256』 - 「技LV+自LV」 = 0
ということはつまり、
『0~「敵の現在のレベル」×255/256』 = 「技LV+自LV」
と同じ意味である。

キャリーフラグが立たないのは、減算して繰り下がりが起きた時である。
『0~「敵の現在のレベル」×255/256』 - 「技LV+自LV」の結果が負の値だと、繰り下がりが起きる。
つまり、『0~「敵の現在のレベル」×255/256』の方が、「技LV+自LV」よりも小さい。
『0~「敵の現在のレベル」×255/256』<「技LV+自LV」
ということである。

まとめると、

『0~「敵の現在のレベル」×255/256』≦「技LV+自LV」

これが成り立つ時に、技が命中する、ということになる。

ここで、

 ・攻撃の命中判定:
LV+技LV>=(0~(敵LV-1))のとき命中

この判定式を思い出していただきたい。

『0~「敵の現在のレベル」×255/256』≦「技LV+自LV」
の右辺と左辺を逆にして表記を書き直すと、

技LV+自LV ≧ 0~敵LV×255/256

こんな感じである。
不等号「」は、プログラミングだと「>=」と同じ意味である。
なので、上の判定式に近い形である。
更に言えば、同じ意味である。

どういうことかというと、「敵LV×255/256」というのは、敵LV×256/256 = 敵LV×1にわずかに足りない値である。
そしてここまでも説明してきたように、スーパーファミコンにおける数値の計算では、小数点以下は切り捨てる。
このため、敵LV×255/256を計算した結果、小数点以下を切り捨てたら、「敵LV-1」と同一なのである。

例:敵LVが16の場合、
16×255/256 = 15.9375
だが、小数点以下切り捨てで「15」と判断される。

という経緯から、

LV+技LV>=(0~(敵LV-1))のとき命中

が成立するのである。
プログラムの内容から、より厳密に表記した場合は、小数点以下切り捨ても配慮し、

技LV+自LV ≧ 0~trunc(敵LV×255/256) なら命中

または、乱数が0~255だということをわかりやすくするのなら、

技LV+自LV ≧ trunc(「乱数(0~255)」×敵LV / 256) なら命中

が、命中判定の計算式であるが、実際に確率を計算する場合は先の「LV+技LV>=(0~(敵LV-1))のとき命中」の方が楽なのは言うまでもない。

$C1/D8A8 BEQ $05    [$D8AF]      ;ゼロフラグが立っている時[$C1/D8AF]にジャンプ
$C1/D8AA BCC $03    [$D8AF]      ;キャリーフラグが立っていない時[$C1/D8AF]にジャンプ
$C1/D8AC LDA #$00                ;※キャリーフラグなしのジャンプ先、Aに$00をロード
$C1/D8AE RTS                     ;※サブルーチン戻り
$C1/D8AF LDA #$FF                ;★Aに$FFをロード
$C1/D8B1 RTS                     ;サブルーチン戻り
;
$C1/D7F7 BEQ $1C    [$D815]      ;ゼロフラグが立っているとき[$C1/D815]にジャンプ(単発ダメージ量計算をスキップ)
$C1/D7F9 LDA $7E9003,x[$7E:AB03] ;Aに[$7E:AB03]をロード(最終的にヒット数の入るメモリ、初期値0)
$C1/D7FD INC A                   ;Aをインクリメント([$7E:AB03]+1)
$C1/D7FE STA $7E9003,x[$7E:AB03] ;A(=1)を[$7E:AB03]に書き込み(ここで「ヒット数は最低でも1」と設定)
$C1/D802 JSR $D81A  [$C1:D81A]   ;

命中判定の計算式は既に判明したが、続きについても少し説明する。
$C1/D8A8$C1/D8AAでは命中するという判定で、[$C1/D8AF]にジャンプするよう指示されている。
この[$C1/D8AF]は、先に行った、

  • 回復技は必中
  • 技の「必中状態異常」と敵の状態異常が一致していたら必中
  • 敵が「眠り」または「マヒ」なら必中

この必中判定の飛び先でもある。
つまり、命中する時には、$C1/D8AF LDA #$FFで、A$FFをロードし、$C1/D7F7へ進むことになる。

一方、命中しない判定だと、頭に※がついた、

$C1/D8AC LDA #$00                ;※キャリーフラグなしのジャンプ先、Aに$00をロード
$C1/D8AE RTS                     ;※サブルーチン戻り

この部分が実行される。
違いは、A$00をロードしていることである。

続いて$C1/D7F7では、ゼロフラグが立っているとき[$C1/D815]にジャンプと指示がある。
A$00をロードした、命中しない判定の時が該当する。
命中しないと[$C1/D815]にジャンプするのだが、これで単発ダメージ量計算のサブルーチンをスキップする。
命中しないのだからダメージ量を計算する必要はない、ということである。

一方、命中する場合、$C1/D7F9に進み、A[$7E:AB03]をロードしている。
この[$7E:AB03]は、ここで読み込みされた時点では、中に$00が入っている。つまりまだ何の処理もされていない、カラの状態のメモリである。
次にINC AA+1しているので、0から1に数値が増加した。
$C1/D7FEで、この「1」を、[$7E:AB03]に書き込みしている。
[$7E:AB03]には、多段ヒット技の場合、この先の計算で値が累積されていき、最終的にヒット数として扱われることになるのだが、ここでまず、「命中する=最低でも1ヒットはする」という意味で「1」を書き込んだのである。
命中しない場合は$00のままである。

この後はまだ少し諸々の処理をしてから、単発ダメージ量計算のサブルーチンに到達することになる。
単発ダメージ量計算サブルーチンの直前の処理について、おまけで紹介しておく。

$C1/D960 LDA $7E900B[$7E:900B]   ;Aに[$7E:900B](技データ10)をロード
$C1/D964 REP #$21                ;Aレジスタは16bit幅, Cフラグクリア
$C1/D966 AND #$0003              ;A(技データ10)と$0003で論理積
$C1/D969 ADC $10    [$00:0310]   ;A + [$00:0310]
$C1/D96B TAX                     ;Aの値をXレジスタに転送

$C1/D960では[$7E:900B]をロードしている。
これは技データ10で、2進数だと上6桁に「LV差係数」、下2桁に「敵依存ステータス」が入っている。
$C1/D966で、$0003(2進数00000011)と論理積を取っているが、これで「敵依存ステータス」が取り出せる。
敵依存ステータスは以下のようになる。

16進数0123
2進数00011011
敵依存ステータス

「敵依存ステータス」が格納される容量は2進数2桁分である。
つまり4種類のデータしか格納できないので、「敵依存ステータス」は必ず「力」「速」「体」「知」のいずれかになる。
味方の「自依存ステータス」のように、自依存ステータスはなし、という設定はできないということになり、実際、技データを見ると敵依存ステータスは4種のうちのどれかに設定されている。

$C1/D969では、取り出した「敵依存ステータス」と[$00:0310]を足している。
この時点で[$00:0310]に入っているのは、この戦闘における敵の番号に当たる。
1B00, 1B10, 1B20,……というように数値が入っており、これに敵依存ステータスの0~3のどれかが足されるので、下1桁が敵依存ステータスの数値になる。
この値は$C1/D96Bで、Xレジスタに転送される。

$C1/D96C SEP #$21                ;Aレジスタは8bit幅, CフラグON
$C1/D96E LDA $81    [$00:0381]   ;Aに[$00:0381](技データ13)をロード
$C1/D970 BPL $1E    [$D990]      ;ネガティブフラグが立っていないとき[$C1/D990]にジャンプ

$C1/D96EA[$00:0381]がロードされるが、ここより前に遡って確認してみると、[$00:0381]には[$7E:901D]の技データ13が入っている。
そしてロードした後に、ネガティブフラグが立つかどうかをBPL $1Eで確認している。
命中判定でも、技データ13を読み込んでネガティブフラグが立つかどうかは、回復技かどうかの判定として使っていた。
回復技なら[$C1/D990]にジャンプせずそのまま処理が進むし、それ以外の攻撃・吸収技は[$C1/D990]にジャンプする。

$C1/D990 LDA $7E8F03,x[$7E:AA??] ;Aに[$7E:AA??](敵の依存ステータス(現在値))をロード
$C1/D994 STA $26    [$00:0326]   ;A(敵の依存ステータス(現在値))を[$00:0326]に書き込み

ここでは$7E8F03,xをロードしている。
つまり、「$7E8F03」にXレジスタを足した数のメモリをロードする。
Xレジスタには、「敵の番号+敵依存ステータス(0~3)」が入っているが、ここでXレジスタを足すと、ちょうど攻撃相手の敵依存ステータスに対応した値が格納されたメモリになるのである。
例えば、ここで敵の番号が「1B00」、「敵依存ステータス」が速(01)なら、Xには「1B01」が入っている。
$7E8F03」に「$1B01」を足すと、「$7EAA04」であるが、このアドレスには敵の「速」の現在値が入っている。
ここで、ダメージ量計算用の敵依存ステータスがロードされたのである。
この値はSTA $26[$00:0326]に入り、ダメージ量計算の時に使われる。

$C1/D996 LDX $10    [$00:0310]   ;Xに[$00:0310](敵番号)をロード
$C1/D998 LDA $7E900A,x[$7E:AB?A] ;Aに[$7E:AB?A](敵の現在レベル)をロード
$C1/D99C STA $25    [$00:0325]   ;A(敵の現在レベル)を[$00:0325]に書き込み

$C1/D996で、再びXに敵の番号[$00:0310]をロードしている。つまり「敵依存ステータス」を呼び出すための値をリセットしたことになる。
$C1/D998LDA $7E900A,xは、「7E900A」に敵の番号を足すことで呼び出すアドレスを指定しているが、指定したアドレスに入っているのは、敵の現在のレベルである。
敵の番号が0なら「$7E900A」に「$1B00」を足して、[$7E:AB0A]の値をロードする。
つまり敵の番号が0, 1, 2, ……なら、敵の現在レベルは、$7E:AB0A, $7E:AB1A, $7E:AB2A, ……に格納されている。

$C1/D99E LDA $7E920A,x[$7E:AD?A] ;Aに[$7E:AD?A]読み込み(おそらく攻撃相手の回避属性関係の値)
$C1/D9A2 STA $27    [$00:0327]   ;Aを[$00:0327]に書き込み
$C1/D9A4 JSR $77CE  [$C1:77CE]   ;[$C1:77CE]へ

$C1/D99ELDA $7E920A,xだが、これも上の敵の現在のレベル呼び出しと似たような処理をしているので、「敵の現在の何らかの値」であるが、おそらく回避属性関係の値である(未確認)。
「ほいこーろー」の仕様でも、最後に$C1/CD39 LDA $7E920A,xという同じ処理が入った後に回避属性の判断が入っていた。
最終的には、回避属性に対応している状況の時、総ダメージ量を÷2+1する処理が入るはずである。

そして$C1/D9A4では、[$C1:77CE]に飛ぶよう指示されており、単発ダメージ量計算のサブルーチンへと飛ぶことになる。



このページをシェアする

上へ