TOP > プログラミング関係解説&調査 > 向き補正(2)

向き補正(2)

当ページの内容は、ある程度のプログラミングの知識を必要とする。
まず、プログラミング関係解説&調査をひととおり読んでいただきたい。

前ページでは味方が敵を攻撃する場合の向き補正のサブルーチンを紹介した。
以下では、敵が味方を攻撃する場合を紹介する。

敵が味方を攻撃する場合

敵が味方を攻撃する場合、敵が複数マスにまたがっているとややこしいことになる。
例えばクルセイダーRSがアキラを攻撃する時、クルセイダーRSの横にアキラが隣接しているとする。
■がクルセイダーRSで、●がアキラとし、アキラが左上向きだとする。
すると、クルセイダーRSの上側に隣接していたら、

正正正側側
正正正側側
正■背背
側■背背背
側側背背背

アキラのすぐ左のマスは正面にあたるのだが、アキラの左下マスは側面にあたる。
このような場合、クルセイダーRSからの攻撃は正面からの攻撃になるのか、それとも側面からの攻撃になるのか?
つまり、どのマスを基準として向きを決めるのか?
が、最大の問題である。

実は、敵の基準マスは乱数で決定している。
といっても、どこかのマスに完全ランダムで決まるということではない。

$C1/E061 LDX $78    [$00:0378]   ;Xに[$00:0378]をロード
$C1/E063 LDA $79    [$00:0379]   ;Aに[$00:0379]をロード
$C1/E065 CMP #$1C                ;Aと$1Cを減算比較(ステータスレジスタ変更のみ)
$C1/E067 BEQ $02    [$E06B]      ;ゼロフラグが立っているとき[$E06B]分岐
$C1/E069 BRA $0B    [$E076]      ;フラグにかかわりなく常に分岐[$E076]
$C1/E076 LDY $0002,x[$00:1BE2]   ;Yに[$00:1BE2]をロード
$C1/E079 JSR $6150  [$C1:6150]   ;[$C1:6150]へジャンプ
;
;戦闘乱数計算
$C1/6150 PHX                     ;↓戦闘乱数計算
;(中略)
$C1/61A4 RTS                     ;乱数がAと[$00:033B]に入る
;
$C1/E07C AND #$01                ;Aと$01で論理積
$C1/E07E STA $10    [$00:0310]   ;Aを[$00:0310]に書き込み
$C1/E080 JSR $6150  [$C1:6150]   ;[$C1:6150]へジャンプ
;
;戦闘乱数計算
;(中略)
$C1/61A4 RTS                     ;乱数がAと[$00:033B]に入る
;
$C1/E083 AND #$01                ;Aと$01で論理積
$C1/E085 STA $11    [$00:0311]   ;Aを[$00:0311]に書き込み
$C1/E087 LDA $000A,x[$00:1BEA]   ;Aに[$00:1BEA](敵のX座標)をロード
$C1/E08A ASL A                   ;Aを算術左シフト *2
$C1/E08B ADC $0004,y[$00:1A44]   ;A + [$00:1A44](敵の横の幅)
$C1/E08E DEC A                   ;Aをデクリメント -1
$C1/E08F ADC $10    [$00:0310]   ;A + [$00:0310](乱数1 & $01 ($00または$01))
$C1/E091 LSR A                   ;Aを論理右シフト (/2)
$C1/E092 STA $12    [$00:0312]   ;Aを[$00:0312]に書き込み
$C1/E094 LDA $000B,x[$00:1BEB]   ;Aに[$00:1BEB](敵のY座標)をロード
$C1/E097 ASL A                   ;Aを算術左シフト *2
$C1/E098 ADC $0005,y[$00:1A45]   ;A + [$00:1A45]
$C1/E09B ADC $11    [$00:0311]   ;A + [$00:0311]
$C1/E09D DEC A                   ;Aをデクリメント -1
$C1/E09E LSR A                   ;Aを論理右シフト (/2)
$C1/E09F STA $13    [$00:0313]   ;Aを[$00:0313]に書き込み
$C1/E0A1 RTS                     ;サブルーチン戻り

$C1/E061からの処理を追っていくと、途中で2回戦闘乱数を生成している。
1回目の乱数は、$C1/E07C$C1/E080の処理で、$01と論理積を取り[$00:0310]に書き込まれている。
$01と論理積を取るということは、下1ビットの値だけ取り出すことになるから、同確率で$00または$01になる。
乱数が奇数か偶数かの判定と言っても良い。

[$00:0310] = 乱数1 & $01 ($00または$01)

2回目の乱数の処理も同じである。
$C1/E083$C1/E085$01と論理積を取り[$00:0311]に書き込んでいる。

[$00:0311] = 乱数2 & $01 ($00または$01)

$C1/E087~からが本題である。
$C1/E087$C1/E092を追っていくと、

[$00:0312] = trunc( (敵のX座標*2 + 敵の横の幅 - 1 + [$00:0310]($00または$01) )/2)

という計算をしている。

□□□□□□□
□□□ク□□
□□□ク□□□
□□□□□□□
□□□□□□□
□□□□□□□
□□□□□□□

という配置で、クルセイダーRSの座標が(3,1)の時ならどうなるかというと、

[$00:0312] = trunc( (3*2 + 1 - 1 + [$00:0310])/2)
= trunc( (6 + [$00:0310])/2)
= 3

[$00:0310]の値が$00でも$01でも、最後に2で割って小数点以下切り捨てだから、必ず3である。
結果として、クルセイダーRSのX座標と同じ値が算出された。
これがX軸の基準座標の計算方法なのである。

もし、横幅が2マスの敵だったらどうなるか?

[$00:0312] = trunc( (3*2 + 2 - 1 + [$00:0310])/2)
= trunc( (7 + [$00:0310])/2)
= 3または4

横幅が2マスの敵だと、X軸の基準座標は確率1/2でどちらかが選ばれることになる。毎回変わるのである。
では、3マスだとどうなるか。

[$00:0312] = trunc( (3*2 + 3 - 1 + [$00:0310])/2)
= trunc( (8 + [$00:0310])/2)
= 4

小数点以下切り捨てなので必ず4になる。
横幅3マスの敵だと、中心のマスを基準座標とするのである。
本作で最大となる横幅4マスの敵は、

[$00:0312] = trunc( (3*2 + 4 - 1 + [$00:0310])/2)
= trunc( (9 + [$00:0310])/2)
= 4または5

中心2マスのどちらかが1/2で選ばれることになる。

ということで、横幅が奇数か偶数かで基準マスがどこかが変わってくる。
更に、$C1/E094$C1/E09FはY軸で同じことをしており、

[$00:0313] = trunc( (敵のY座標*2 + 敵の縦の幅 - 1 + [$00:0311]($00または$01) )/2)

これがY軸での基準マスの決定方法である。
クルセイダーRSは縦2マスサイズだから、乱数によって、どちらが基準マスか決まることになる。
クルセイダーRSの座標が(3,1)の時、

[$00:0313] = trunc( (1*2 + 2 - 1 + [$00:0311]($00または$01) )/2)
= trunc( (3 + [$00:0311])/2)
= 1または2

[$00:0311]$00ならY軸での基準マスは1$01ならY軸での基準マスは2となる。
ということで、

正正正側側
正正正側側
正■背背
側■背背背
側側背背背

この配置の時、アキラは正面から攻撃をくらったことになるのか、側面から攻撃をくらったことになるのかは、確率1/2でどちらかになるのでどちらになるか予測不可というのが正解なのである。
側面から攻撃をくらった方がダメージ量などが上がって危険だから、

正正正側側
正■正側側
正■背背
側側背背背
側側背背背

もしどうしても敵から攻撃をくらわなければならない状態だというのなら、敵がいるマスを上のようにすべて正面位置に入れれば、必ず正面からの攻撃になり、少なくとも側面からの攻撃を食らうことはない。
ただ、3マス以上の大型の敵の場合、

正正正正側側
■■■正側側
■■■背背
■■■背背背
側側側背背背

たとえば3×3マスサイズの敵なら、上の計算の通り、敵の中心位置が基準マスになることが確定である。
よって、上配置でも、正面からの攻撃として判定されることになる。
敵サイズからどの範囲が基準マスになるかを判断すれば良いことになる。
(本作はそこまで難しく考えなくてもどうにかなるゲームではあるが、制限プレイなどでは役立つ知識だろう)

さて、敵の基準マスの値は、[$00:0312]にX軸の値、[$00:0313]にY軸の値が入るとわかったところで、続きを追ってみよう。
今回は基準マスが下側、つまり側面からの攻撃になった前提で処理を追ってみる。
アキラの座標は(4,1)で左上向き、クルセイダーRSの座標は(3,1)、クルセイダーRSの基準座標(いわば中心座標)は(3,2)である。

□□□□□□□
□□□ク□□
□□□ク□□□
□□□□□□□
□□□□□□□
□□□□□□□
□□□□□□□
$C1/D200 LDY $0002,x[$00:1C02]   ;Yに[$00:1C02]をロード
$C1/D203 STZ $10    [$00:0310]   ;[$00:0310]に$00を書き込み
$C1/D205 LDA $001D,x[$00:1C1D]   ;Aに[$00:1C1D](アキラの向き)をロード
$C1/D208 STA $11    [$00:0311]   ;A(アキラの向き)を[$00:0311]に書き込み
$C1/D20A LDA $0018,x[$00:1C18]   ;Aに[$00:1C18](アキラのX座標)をロード
$C1/D20D CMP $12    [$00:0312]   ;Aと[$00:0312](敵X軸基準マス)を減算比較(ステータスレジスタ変更のみ)
$C1/D20F BEQ $16    [$D227]      ;ゼロフラグが立っているとき[$D227]分岐
$C1/D211 BPL $08    [$D21B]      ;ネガティブフラグが立っていないとき[$D21B]分岐
$C1/D21B LDA $11    [$00:0311]   ;Aに[$00:0311](アキラの向き)をロード
$C1/D21D BIT #$01                ;Aと$01で論理積(ステータスフラグ変更のみ)
$C1/D21F BNE $02    [$D223]      ;ゼロフラグが立っていないとき[$D223]分岐
$C1/D223 LDA #$01                ;Aに$01をロード
$C1/D225 BRA $02    [$D229]      ;フラグにかかわりなく常に分岐[$D229]
$C1/D229 STA $10    [$00:0310]   ;Aを[$00:0310]に書き込み
$C1/D22B LDA $0019,x[$00:1C19]   ;Aに[$00:1C19](アキラのY座標)をロード
$C1/D22E CMP $13    [$00:0313]   ;Aと[$00:0313](敵Y軸基準マス)を減算比較(ステータスレジスタ変更のみ)
$C1/D230 BEQ $16    [$D248]      ;ゼロフラグが立っているとき[$D248]分岐
$C1/D232 BPL $08    [$D23C]      ;ネガティブフラグが立っていないとき[$D23C]分岐
$C1/D234 LDA $11    [$00:0311]   ;Aに[$00:0311](アキラの向き)をロード
$C1/D236 BIT #$02                ;Aと$02で論理積(ステータスフラグ変更のみ)
$C1/D238 BEQ $0A    [$D244]      ;ゼロフラグが立っているとき[$D244]分岐
$C1/D23A BRA $12    [$D24E]      ;フラグにかかわりなく常に分岐[$D24E]
;
$C1/D24E LDA $0038,x[$00:1C38]   ;Aに[$00:1C38](アキラのLV(現在値))をロード
$C1/D251 STA $11    [$00:0311]   ;A(アキラのLV(現在値))を[$00:0311]に書き込み
$C1/D253 LDA $14    [$00:0314]   ;Aに[$00:0314](=技データ13[$7E:901D] & $0F 技の属性)をロード
$C1/D255 BEQ $1D    [$D274]      ;ゼロフラグが立っているとき[$D274]分岐
$C1/D257 STA $08    [$00:0308]   ;Aを[$00:0308]に書き込み
$C1/D259 LDY $0002,x[$00:1C02]   ;Yに[$00:1C02]をロード
$C1/D25C REP #$21                ;Aを16bit幅に変更、キャリーフラグクリア
$C1/D25E LDA $0021,y[$00:0EA1]   ;Aに[$00:0EA2][$00:0EA1](アキラの回避属性2バイト)をロード
$C1/D261 ORA $0032,y[$00:0EB2]   ;Aと[$00:0EB3][$00:0EB2](アキラの装備の回避属性2バイト)で論理和
$C1/D264 XBA                     ;Aレジスタの上位バイトと下位バイトを交換
;
;回避属性ループ処理
$C1/D265 ASL A                   ;Aを算術左シフト *2
$C1/D266 DEC $08    [$00:0308]   ;[$00:0308]をデクリメント -1
$C1/D268 BNE $FB    [$D265]      ;ゼロフラグが立っていないとき[$D265]分岐
;回避属性ループ処理ここまで
;
$C1/D26A SEP #$20                ;MフラグON Aレジスタは8bit幅
$C1/D26C BCC $04    [$D272]      ;キャリーフラグが立っていないとき[$D272]分岐
$C1/D272 LDA #$00                ;Aに$00をロード
$C1/D274 STA $7ECE35,x[$7E:EA35] ;Aを[$7E:EA35]に書き込み
;
$C1/D278 LDA $10    [$00:0310]   ;Aに[$00:0310]($01)をロード
$C1/D27A AND #$05                ;Aと$05で論理積
$C1/D27C BEQ $16    [$D294]      ;ゼロフラグが立っているとき[$D294]分岐
$C1/D27E CMP #$05                ;Aと$05を減算比較(ステータスレジスタ変更のみ)
$C1/D280 BEQ $15    [$D297]      ;ゼロフラグが立っているとき[$D297]分岐
$C1/D282 LDA $10    [$00:0310]   ;Aに[$00:0310]($01)をロード
$C1/D284 AND #$0A                ;Aと$0Aで論理積
$C1/D286 BNE $0F    [$D297]      ;ゼロフラグが立っていないとき[$D297]分岐
$C1/D288 LDA $11    [$00:0311]   ;Aに[$00:0311]をロード
$C1/D28A SEC                     ;キャリーフラグON
$C1/D28B SBC $001C,y[$00:0E9C]   ;A - [$00:0E9C](アキラ側面補正)
$C1/D28E BCS $09    [$D299]      ;キャリーフラグが立っているとき[$D299]分岐
$C1/D299 STA $002E,x[$00:1C2E]   ;Aを[$00:1C2E]に書き込み
$C1/D29C RTS                     ;サブルーチン戻り

$C1/D200$C1/D29Cまで連続した処理なのですべて載せたが、途中の$C1/D253$C1/D274に回避属性でのダメージ半減があるかないかの判定が挟まっている。
まず、前半の$C1/D200$C1/D23Aを見てみよう。

$C1/D200 LDY $0002,x[$00:1C02]   ;Yに[$00:1C02]をロード
$C1/D203 STZ $10    [$00:0310]   ;[$00:0310]に$00を書き込み
$C1/D205 LDA $001D,x[$00:1C1D]   ;Aに[$00:1C1D](アキラの向き)をロード
$C1/D208 STA $11    [$00:0311]   ;A(アキラの向き)を[$00:0311]に書き込み
$C1/D20A LDA $0018,x[$00:1C18]   ;Aに[$00:1C18](アキラのX座標)をロード
$C1/D20D CMP $12    [$00:0312]   ;Aと[$00:0312](敵X軸基準マス)を減算比較(ステータスレジスタ変更のみ)
$C1/D20F BEQ $16    [$D227]      ;ゼロフラグが立っているとき[$D227]分岐
;ゼロフラグOFF [$00:1C18]-[$00:0312]=4-3
$C1/D211 BPL $08    [$D21B]      ;ネガティブフラグが立っていないとき[$D21B]分岐
;ネガティブフラグOFF [$00:1C18]-[$00:0312]=4-3
$C1/D21B LDA $11    [$00:0311]   ;Aに[$00:0311](アキラの向き)をロード
$C1/D21D BIT #$01                ;Aと$01で論理積(ステータスフラグ変更のみ)
$C1/D21F BNE $02    [$D223]      ;ゼロフラグが立っていないとき[$D223]分岐
;ゼロフラグOFF($00(右下向き)か$02(右上向き)のどちらでもない)
$C1/D223 LDA #$01                ;Aに$01をロード
$C1/D225 BRA $02    [$D229]      ;フラグにかかわりなく常に分岐[$D229]
$C1/D229 STA $10    [$00:0310]   ;Aを[$00:0310]に書き込み
;
$C1/D22B LDA $0019,x[$00:1C19]   ;Aに[$00:1C19](アキラのY座標)をロード
$C1/D22E CMP $13    [$00:0313]   ;Aと[$00:0313](敵Y軸基準マス)を減算比較(ステータスレジスタ変更のみ)
$C1/D230 BEQ $16    [$D248]      ;ゼロフラグが立っているとき[$D248]分岐
;ゼロフラグOFF [$00:1C19]-[$00:0313]=1-2
$C1/D232 BPL $08    [$D23C]      ;ネガティブフラグが立っていないとき[$D23C]分岐
;ネガティブフラグON [$00:1C19]-[$00:0313]=1-2
$C1/D234 LDA $11    [$00:0311]   ;Aに[$00:0311](アキラの向き)をロード
$C1/D236 BIT #$02                ;Aと$02で論理積(ステータスフラグ変更のみ)
$C1/D238 BEQ $0A    [$D244]      ;ゼロフラグが立っているとき[$D244]分岐
;ゼロフラグOFF(上向き)
$C1/D23A BRA $12    [$D24E]      ;フラグにかかわりなく常に分岐[$D24E]

まず、[$00:1C1D](アキラの向き)を[$00:0311]にコピーする。
味方キャラの向きは、敵の向きとは異なり、$00$03で表記されている点に注意。
今回アキラは左上向きで、[$00:0311]に入るのは$03である。

その後、[$00:1C18](アキラのX座標)と[$00:0312](敵X軸基準マス)を減算比較する。
アキラの座標は(4,1)、クルセイダーRSの基準座標は(3,2)だから、$C1/D20Fのゼロフラグ判定はOFF、$C1/D211のネガティブフラグ判定もOFFである。
つまりアキラがクルセイダーRS(の基準マス)より右の位置にいるという判定が$C1/D21B~である。

$C1/D21B[$00:0311](アキラの向き)をロードし、まず$01と論理積を取ってゼロフラグ判定をしている。
向きは$00$03のいずれかだが、$01と論理積を取ってゼロフラグが立つのは、$00(右下向き)か$02(右上向き)のいずれかである。
つまり、ここで右向きか左向きかの判定をしており、ゼロフラグが立たないなら左向き確定である。
この時点で[$00:0310]$01を書き込み、続いて$C1/D22B~のY座標判定に移る。

$C1/D22Bからは、[$00:1C19](アキラのY座標)と[$00:0313](敵Y軸基準マス)を減算比較している。
[$00:1C19] - [$00:0313] = 1 - 2なので、負の値となることから、ネガティブフラグがONとなり、$C1/D234に進む。
ここで、アキラがクルセイダーRS(の基準マス)より上にいるという判定になる。
今回はクルセイダーRSの基準マスが下側なので、上にいるという判定だが、基準マスが上側だったらY軸が同マスになって$C1/D230でゼロフラグが立ち、処理が変わっていたことになる。

とりあえずネガティブフラグONの$C1/D234以降を見てみると、[$00:0311](アキラの向き)と$02で論理積をとり、ゼロフラグ判定をしている。
向きは$00$03のいずれかだが、$02と論理積を取ってゼロフラグが立つのは、$00(右下向き)か$01(左下向き)のいずれかである。
つまり、ここで上向きか下向きかの判定をしており、ゼロフラグが立たないなら上向き確定である。

  • アキラがクルセイダーRS(の基準マス)より右にいる
  • アキラが左向きである
  • アキラがクルセイダーRS(の基準マス)より上にいる
  • アキラが上向きである

という4つの判定の結果、クルセイダーRS(の基準マス)が下図の■のどこかにあるので側面からの攻撃と判定されたことになる。

□□□□□□□
□□□□□□
■■■■□□□
■■■■□□□
■■■■□□□
■■■■□□□
■■■■□□□

[$00:0310]$01を書き込んだが、これが後々の向きの判定値である。

$C1/D200$C1/D24Eまで、分岐込みのサブルーチンは以下。

$C1/D200 LDY $0002,x[$00:1C02]   ;Yに[$00:1C02]をロード
$C1/D203 STZ $10    [$00:0310]   ;[$00:0310]に$00を書き込み
$C1/D205 LDA $001D,x[$00:1C1D]   ;Aに[$00:1C1D](アキラの向き)をロード
$C1/D208 STA $11    [$00:0311]   ;A(アキラの向き)を[$00:0311]に書き込み
$C1/D20A LDA $0018,x[$00:1C18]   ;Aに[$00:1C18](アキラのX座標)をロード
$C1/D20D CMP $12    [$00:0312]   ;Aと[$00:0312](敵X軸基準マス)を減算比較(ステータスレジスタ変更のみ)
$C1/D20F BEQ $16    [$D227]      ;ゼロフラグが立っているとき[$D227]分岐
;ゼロフラグOFF(アキラのX座標-敵X軸基準マス=0ではない)
$C1/D211 BPL $08    [$D21B]      ;ネガティブフラグが立っていないとき[$D21B]分岐
;ネガティブフラグON(アキラのX座標-敵X軸基準マスが負の値)
$C1/D213 LDA $11    [$00:0311]   ;Aに[$00:0311](アキラの向き)をロード
$C1/D215 BIT #$01                ;Aと$01で論理積(ステータスフラグ変更のみ)
$C1/D217 BEQ $0A    [$D223]      ;ゼロフラグが立っているとき[$D223]分岐
;ゼロフラグOFF(左向き)
$C1/D219 BRA $10    [$D22B]      ;フラグにかかわりなく常に分岐[$D22B]
;$C1/D211でネガティブフラグOFF(アキラのX座標-敵X軸基準マスが正の値)
$C1/D21B LDA $11    [$00:0311]   ;Aに[$00:0311](アキラの向き)をロード
$C1/D21D BIT #$01                ;Aと$01で論理積(ステータスフラグ変更のみ)
$C1/D21F BNE $02    [$D223]      ;ゼロフラグが立っていないとき[$D223]分岐
;ゼロフラグON(右向き)
$C1/D221 BRA $08    [$D22B]      ;フラグにかかわりなく常に分岐[$D22B]
;$C1/D217でゼロフラグON(右向き)、または$C1/D21FでゼロフラグOFF(左向き)
$C1/D223 LDA #$01                ;Aに$01をロード
$C1/D225 BRA $02    [$D229]      ;フラグにかかわりなく常に分岐[$D229]
;$C1/D20FでゼロフラグON(アキラのX座標-敵X軸基準マス=0)
$C1/D227 LDA #$02                ;Aに$02をロード
$C1/D229 STA $10    [$00:0310]   ;Aを[$00:0310]に書き込み
$C1/D22B LDA $0019,x[$00:1C19]   ;Aに[$00:1C19](アキラのY座標)をロード
$C1/D22E CMP $13    [$00:0313]   ;Aと[$00:0313](敵Y軸基準マス)を減算比較(ステータスレジスタ変更のみ)
$C1/D230 BEQ $16    [$D248]      ;ゼロフラグが立っているとき[$D248]分岐
;ゼロフラグOFF(アキラのY座標-敵Y軸基準マス=0ではない
$C1/D232 BPL $08    [$D23C]      ;ネガティブフラグが立っていないとき[$D23C]分岐
;ネガティブフラグON(アキラのY座標-敵Y軸基準マスが負の値)
$C1/D234 LDA $11    [$00:0311]   ;Aに[$00:0311](アキラの向き)をロード
$C1/D236 BIT #$02                ;Aと$02で論理積(ステータスフラグ変更のみ)
$C1/D238 BEQ $0A    [$D244]      ;ゼロフラグが立っているとき[$D244]分岐
;ゼロフラグOFF(上向き)
$C1/D23A BRA $12    [$D24E]      ;フラグにかかわりなく常に分岐[$D24E]
;$C1/D232でネガティブフラグOFF(アキラのY座標-敵Y軸基準マスが正の値)
$C1/D23C LDA $11    [$00:0311]   ;Aに[$00:0311](アキラの向き)をロード
$C1/D23E BIT #$02                ;Aと$02で論理積(ステータスフラグ変更のみ)
$C1/D240 BNE $02    [$D244]      ;ゼロフラグが立っていないとき[$D244]分岐
;ゼロフラグON(下向き)
$C1/D242 BRA $0A    [$D24E]      ;フラグにかかわりなく常に分岐[$D24E]
;$C1/D238でゼロフラグON(下向き)、$C1/D240でゼロフラグOFF(上向き)
$C1/D244 LDA #$04                ;Aに$04をロード
$C1/D246 BRA $02    [$D24A]      ;フラグにかかわりなく常に分岐[$D24A]
;$C1/D230でゼロフラグON アキラのY座標-敵Y軸基準マス=0
$C1/D248 LDA #$08                ;Aに$08をロード
;合流
$C1/D24A ORA $10    [$00:0310]   ;Aと[$00:0310]で論理和
$C1/D24C STA $10    [$00:0310]   ;Aを[$00:0310]に書き込み
$C1/D24E LDA $0038,x[$00:1C38]   ;Aに[$00:1C38]をロード

$C1/D200$C1/D229がX座標判定で、$C1/D22B$C1/D24CがY座標判定である。
[$00:0310]には初期値として$00が入るが、まずX座標判定で[$00:0310]に入る値が5パターンに分かれる。

判定[$00:0310]
味方のX座標-敵X軸基準マス=0$02
味方のX座標-敵X軸基準マス<0 かつ、右向き$00
味方のX座標-敵X軸基準マス<0 かつ、左向き$01
味方のX座標-敵X軸基準マス>0 かつ、右向き$01
味方のX座標-敵X軸基準マス>0 かつ、右向き$00

[$00:0310]の下2ビットしか値が変更されていない。
また、$00が入る時は、味方キャラは敵の方向を向いておらず、$01が入る時は、味方キャラは敵の方向を向いていることになる。

更に、Y座標判定も5パターンに分岐するが、最終的にAに書き込んだ値を先の[$00:0310]と加算する。
加算前のAの値は以下の通り。

判定A
味方のY座標-敵Y軸基準マス=0$08
味方のY座標-敵Y軸基準マス<0 かつ、上向き$00
味方のY座標-敵Y軸基準マス<0 かつ、下向き$04
味方のY座標-敵Y軸基準マス>0 かつ、上向き$04
味方のY座標-敵Y軸基準マス>0 かつ、下向き$00

[$00:0310]の下3~4ビットしか値が変更されていない。
また、$00が入る時は、味方キャラは敵の方向を向いておらず、$04が入る時は、味方キャラは敵の方向を向いていることになる。

以上の2回の判定を加算すると[$00:0310]になる。
なお、「味方のX座標-敵X軸基準マス=0」かつ「味方のY座標-敵Y軸基準マス=0」だと敵と重なってしまうので、このパターンのみ存在しない。
また、加算時、下4ビットの中で、一番下のビットか、3ビット目に1が入る時(%0101のように)は敵の方向を向いていることになる。
X軸でもY軸でも敵の方向を向いていると正面向きになるが、この時は必ず[$00:0310]$01 + $04 = $05が入る。

先に示した例は、
アキラのX座標-敵X軸基準マス<0 かつ、左向き」
アキラのY座標-敵Y軸基準マス<0 かつ、上向き」
なので、[$00:0310] = $01 + $00である。

また、[$00:0310]に入る値は$00$09のいずれかになるはずだ。

では、後半部の$C1/D278~を見てみよう。
[$00:0310]$01が入っている前提で処理を見てみる。

$C1/D278 LDA $10    [$00:0310]   ;Aに[$00:0310]($01)をロード
$C1/D27A AND #$05                ;Aと$05(%0000 0101)で論理積
$C1/D27C BEQ $16    [$D294]      ;ゼロフラグが立っているとき[$D294]分岐
;ゼロフラグOFF
$C1/D27E CMP #$05                ;Aと$05を減算比較(ステータスレジスタ変更のみ)
$C1/D280 BEQ $15    [$D297]      ;ゼロフラグが立っているとき[$D297]分岐
;ゼロフラグOFF($01-$05)
$C1/D282 LDA $10    [$00:0310]   ;Aに[$00:0310]($01)をロード
$C1/D284 AND #$0A                ;Aと$0A(%0000 1010)で論理積
$C1/D286 BNE $0F    [$D297]      ;ゼロフラグが立っていないとき[$D297]分岐
;ゼロフラグON
$C1/D288 LDA $11    [$00:0311]   ;Aに[$00:0311](アキラのLV(現在値))をロード
$C1/D28A SEC                     ;キャリーフラグON
$C1/D28B SBC $001C,y[$00:0E9C]   ;A - [$00:0E9C](アキラ側面補正)
$C1/D28E BCS $09    [$D299]      ;キャリーフラグが立っているとき[$D299]分岐
$C1/D299 STA $002E,x[$00:1C2E]   ;Aを[$00:1C2E]に書き込み
$C1/D29C RTS                     ;サブルーチン戻り

[$00:0310]$05の論理積が0ではない、かつ、[$00:0310] - $050ではない、かつ、[$00:0310]$0Aの論理積が0ではないと、側面からの攻撃と判断され、$C1/D288に進む。
アキラのLV(現在値) - [$00:0E9C](アキラ側面補正)[$00:1C2E]に書き込まれて、補正込みのレベルとして扱われることになる。

さて、$C1/D278$C1/D29Cのサブルーチンを分岐込みで見てみると以下のようになる。

$C1/D278 LDA $10    [$00:0310]   ;Aに[$00:0310]をロード
$C1/D27A AND #$05                ;Aと$05(%0000 0101)で論理積
$C1/D27C BEQ $16    [$D294]      ;ゼロフラグが立っているとき[$D294]分岐
;ゼロフラグOFF(正面または側面)
$C1/D27E CMP #$05                ;Aと$05を減算比較(ステータスレジスタ変更のみ)(正面だとここで0)
$C1/D280 BEQ $15    [$D297]      ;ゼロフラグが立っているとき[$D297]分岐
;ゼロフラグOFF(側面)
$C1/D282 LDA $10    [$00:0310]   ;Aに[$00:0310]をロード
$C1/D284 AND #$0A                ;Aと$0Aで論理積
$C1/D286 BNE $0F    [$D297]      ;ゼロフラグが立っていないとき[$D297]分岐
;ゼロフラグON
$C1/D288 LDA $11    [$00:0311]   ;Aに[$00:0311](味方キャラのLV(現在値))をロード
$C1/D28A SEC                     ;キャリーフラグON
$C1/D28B SBC $001C,y[$00:1A5C]   ;A - [$001C,y](側面補正)または[$001C,y+1](背面補正)
$C1/D28E BCS $09    [$D299]      ;キャリーフラグが立っているとき[$D299]分岐
;キャリーフラグOFF
$C1/D290 LDA #$00                ;Aに$00をロード
$C1/D292 BRA $05    [$D299]      ;フラグにかかわりなく常に分岐[$D299]
;$C1/D27CでゼロフラグON(背面補正)
$C1/D294 INY                     ;Yをインクリメント +1
$C1/D295 BRA $F1    [$D288]      ;フラグにかかわりなく常に分岐[$D288]
;$C1/D280ゼロフラグON(正面)、C1/D286ゼロフラグOFF
$C1/D297 LDA $11    [$00:0311]   ;Aに[$00:0311](味方キャラのLV(現在値))をロード
$C1/D299 STA $002E,x[$00:1C2E]   ;Aを[$00:1C2E]に書き込み
$C1/D29C RTS                     ;サブルーチン戻り

$C1/D278$C1/D27C[$00:0310]$05で論理積を取りゼロフラグ判定になるが、ここでゼロフラグが立つのはX軸でもY軸でも敵の方を向いていない、つまり一番下のビットと3番目のビット両方に0が入っている時である。
この場合は背面から攻撃されたという判定確定で、$C1/D294にジャンプする。
そこではY+1してから$C1/D288に進む。
$C1/D288以降は側面の処理との合流になるので説明は後にする。

$C1/D27Eに進む場合は正面または側面から攻撃されたことになる。
$C1/D27E$C1/D280で、「[$00:0310] & $05」が$05かどうかの判定になる。
先に述べた通り、X軸もY軸も敵の方向を向いている時は、一番下のビットと3番目のビット両方に1が立ち、正面から攻撃されたことになる。
よって、ここでゼロフラグが立つと正面からの攻撃で確定となり、$C1/D297にジャンプする。

ここで残った場合、$C1/D282~の処理に進む。
[$00:0310]$0A(%0000 1010)で論理積を取り、ゼロフラグ判定を行う。
上から4桁目または2桁目に1が立っているのは、敵の基準マスのX軸またはY軸と一致している時。
この時は正面からの攻撃判定でゼロフラグが立たず、$C1/D297にジャンプする。

残ったのは側面からの攻撃になる。
$C1/D288~の処理になるのだが、この処理は背面からの処理と合流である。
異なるのは、背面だとYの値が+1されていることのみである。
ここではキャリーフラグを立てて、

[$00:0311](味方キャラのLV(現在値)) - [$001C,y]

を計算するが、[$001C,y]はシナリオ別キャラデータの側面補正の値または背面補正の値になる。
アキラなら[$00:0E9C]が側面補正、[$00:0E9D]が背面補正である。
Yの値で、側面補正と背面補正のどちらを呼び出すか決まることになるが、背面補正の場合は$C1/D294Yをインクリメント(+1)して呼び出しているのである。
この減算でキャリーフラグが立つ、つまり減算で負の値になったら、A$00をロードし、$C1/D299に飛び、減算結果を[$00:1C2E]に書き込む。
正面からの攻撃の場合は減算せず、[$00:0311](味方キャラのLV(現在値))がそのまま[$00:1C2E]に書き込まれる。

ということで、敵が味方に攻撃する場合は少々ややこしくなるものの、上のように計算して向き補正が決められる。



このページをシェアする

上へ