DQ3 エンカウント時の出現モンスター決定方法2

今回からプログラム部分の実装を見ていきます。エンカウントの解析する上で一番やっかいなのは「RAMアクセスが多すぎて、そのアドレスの意味が何を表しているのかよくわからない」ことです。普通はその場で固定長のデータアクセス用のSRをコールするので、その場その場でこのアドレスにはどの値がセットされるというのはすぐわかるのですが、必要なパラメーターが多すぎるためにあらかじめ用意したRAM領域にごそっとコピーしてから処理を開始する、という実装になっているようです。この処理はSR: $068195で行っているので、それぞれの値がどのアドレスにセットされるのかをまずまとめておきます(その1のエントリ参照のこと)。なお、このSRでは延々とエンカウント、エンカウント種別から値を取得してRAMにセット、という処理しかしていないのでここでは省略します。

  • $067DF5 エンカウント準備
c=on
067E06JSR $8195SR: $068195エンカウント固定情報設定
067E09LDA #$3FFFA=#$3FFF混成モンスター1から固定パーティ2まで14種類が選択対象
067E0CJSR $8059SR: $068059出現モンスター決定
067E0FJSR $7E89SR: $($067E89+X)
067E12JSR $7E19SR: $067E19最大出現数を見て出現モンスター数調整(画面幅考慮なし)
c=on

  • SR: $068059 出現モンスター決定
068059STA $1C$00001C=A選択する種別をセット
06805BSTZ $1E$00001E=#$00
06805DSTZ $20$000020=#$00
06805FLDX #$0000X=#$0000
068062LSR $1C$00001C>>1
068064BCC #$0Bif(c==off) goto $068071
068066LDA $F798,XA=$7EF798+X
068069CLCc=off
06806ABEQ #$05if(z==on) goto $068071
06806CADC $20A+=$000020
06806ESTA $20$000020=A
068070SECc=on
068071ROR $1E($00001E+C)>>1
068073INXX++
068074INXX++
068075CPX #$0020X>=#$0020 ?
068078BCC #$E8if(c==off) goto $068062
06807ALDA $20A=$000020
06807CDECA–
06807DBMI #$24if(n==on) goto $0680A3
06807FJSL $00133ESR: $00133E乱数発生 00-A A(1B)
068083PHAPush A
068084STZ $20$000020=#$00
068086LDX #$0000X=#$0000
068089LSR $1E$00001E>>1
06808BBCC #$0Eif(c==off) goto $06809B
06808DLDA $F798,XA=$7EF798+X
068090CLCc=off
068091ADC $20A+=$000020
068093STA $20$000020=A
068095LDA $01,SA=Stack($01)
068097CMP $20A>=$000020?
068099BCC #$0Fif(c==off) goto $0680AA
06809BINXX++
06809CINXX++
06809DCPX #$0020X>=#$0020 ?
0680A0BCC #$E7if(c==off) goto $068089
0680A2PLAPull A
0680A3LDX #$001CX=#$001C
0680A6LDA #$0000A=#$0000
0680A9RTSreturn
0680AAPLAPull A
0680ABLDA $F7B8,XA=$7EF7B8+X出現モンスターIDを取得
0680AERTSreturn

よくわからない処理が延々と続きます。ここで覚えておいてもらいたいのは、混成モンスター1から固定パーティ2まで順番に0から13のインデックスが振られていること、さらにエンカウント種別の0~13バイトの1バイトずつの値がこれに対応した閾値?であるということです。このSRの処理は、各閾値を順番に合計していき、0から合計値までの乱数をとり、乱数の値を含んでいる閾値を特定する、というものです。早い話が幅が一定でないルーレットみたいなものです。同じ仕組みはすごろくのパネルに止まったときのイベント発生判定時にも使用されていました。

当然ながらモンスターIDが設定されていないインデックスはそもそも選択肢から除外されます。さらに、このSRを呼ぶ直前でAレジスタにセットされた値も影響します。$067E0A-で#$3FFFがセットされていますが、これを2進数にすると0011111111111111となり、右から順番に各ビットが混成モンスター1から固定パーティ2に相当します。これがOFFになっていると、これまたモンスター選択から除外されます。例えば、#0FFFの場合は、固定パーティ1,2は選択されないことを意味します。ここでは#$03FFFとなっているので14種すべてが選択される可能性があることを意味します。ちなみに、昼の場合は夜のみ出現モンスター(ID:10)、固定パーティ2(夜のみ出現,ID:13)はSR: $068195の時点で0がセットされているのでそもそも選択肢には入りません。

  • アリアハン周辺の例

エンカウント(ID:#$09)

混1混2混3混4混5単1単2単3単4ソロ固1固2
おおがらすスライムいっかくうさぎおおありくい(空)(空)いっかくうさぎスライムおおがらすおおありくい(空)(空)0000

エンカウント種別(ID:#$01)

混1混2混3混4混5単1単2単3単4ソロ固1固2
2020151530202010151040111515

(赤字は対象外)

合計値 125(=20+20+15+15+20+10+15+10)で、0から125までの乱数を取る。乱数の結果が73だったら、単1(71~90)が選択される。

※SR: $068059をコールする前にAレジスタに#000Fをセットしていた場合(混1-4のみ有効になる)

エンカウント種別(ID:#$01)

混1混2混3混4混5単1単2単3単4ソロ固1固2
2020151530202010151040111515

(赤字・青字は対象外)

合計値 70(=20+20+15+15)で、0から70までの乱数を取る。乱数の結果が30だったら、混2(21~40)が選択される。

ちなみに、この閾値の合計は255以下であることが必須になります。超えると乱数の取られる範囲が下位1バイトのみになって出現パターンが偏ることになる(多分)なので閾値をいじる場合は注意が必要です。

このSRを出るとAレジスタには決定されたモンスターID、Xレジスタには0-13のオフセット(0-26)がセットされています。このXの値によって$067E0Fで呼ばれるSRが変わります。

  • $67E89- エンカウント時モンスター決定処理SRアドレス(2Byte*14rec)
インデックス開始ドレス
007F01混成モンスター1用
017F01混成モンスター2用
027F01混成モンスター3用
037F01混成モンスター4用
047F01混成モンスター5用
057F581体のみ+混成5種をお供にするモンスター用
067F71単一種出現モンスター1用
077F71単一種出現モンスター2用
087F71単一種出現モンスター3用
097F71単一種出現モンスター4用
0A7F71夜のみモンスター用
0B7FAE1体のみ出現用
0C7FB5固定パーティ1用
0D7FB5固定パーティ2用
0E8058

長くなったのでこの辺で。次回はそれぞれのSRでどのように1体目以降の出現モンスターが決定されるか見ていきます。

コメント

タイトルとURLをコピーしました