DQ6戦闘部分解説9

相当サボっていますがとりあえずあまりネタを考えるのに頭を使わなくていいところから作業をしていきます。というわけで前回の続き、戦闘コマンド入力「たたかう」を見ていきます。

  • SR:$0238BB 戦闘コマンド処理_SRアドレス_戦う
0238BB JSL $C42B1C SR: $042B1C 引数:1#$01 引数:2#$FF パーティ人数取得
0238C1 PHA Push A
0238C2 LDY #$0000 Y=#$0000
0238C5 JSL $C2BB34 SR: $02BB34 戦闘中キャラクターIDから通常キャラクターIDへ変換
0238C9 STX $258B $258B=X
0238CC JSR $3965 SR: $023965 コマンド入力の必要があるか(ないc=on)
0238CF BCS #$55 if(c==on) goto $023926
0238D1 JSL $C2CAC6 SR: $02CAC6
0238D5 STY $386E $386E=Y
0238D8 LDA #$00DA A=#$00DA 戦闘コマンド入力のウィンドウID
0238DB JSL $C37236 SR: $037236 ウィンドウ描画+ユーザー入力を得る(キャンセルc=on)
0238DF BCS #$4E if(c==on) goto $02392F
0238E1 LDX $258B X=$258B
0238E4 JSL $C2C331 SR: $02C331
0238E8 LDX #$000A X=#$000A
0238EB LDA $3874 A=$3874
0238EE CMP $C2394D,X A==$02394D+X?
0238F2 BEQ #$06 if(z==on) goto $0238FA
0238F4 DEX X–
0238F5 DEX X–
0238F6 BPL #$F6 if(n==off) goto $0238EE
0238F8 BRA #$FE goto $0238F8
0238FA JSR $3959 SR: $($023959+X) 戦闘コマンド各種処理
0238FD BCC #$06 if(c==off) goto $023905
0238FF JSL $C3B0B9 SR: $03B0B9 ウィンドウ消去(フェードなし)
023903 BRA #$DA goto $0238DF
023905 LDX $258B X=$258B
023908 JSL $C2EFA7 SR: $02EFA7 引数:1#$2052 引数:2#$0002 混乱中かチェック
023910 BEQ #$14 if(z==on) goto $023926
023912 LDA #$8198 A=#$8198 混乱していたら「行動直前に戦闘行動を決定」の戦闘行動・対象値に差し替え
023915 JSL $C2EF6B SR: $02EF6B 引数:1#$2034
02391B LDA #$0000 A=#$0000
02391E JSL $C2F034 SR: $02F034 引数:1#$2061 引数:2#$0080
023926 INY Y++
023927 TYA A=Y
023928 CMP $01,S A>=Stack($01)?
02392A BCC #$99 if(c==off) goto $0238C5
02392C PLA Pull A
02392D CLC c=off
02392E RTS return
02392F DEY Y– 戦闘コマンドキャンセル時の処理
023930 BMI #$18 if(n==on) goto $02394A
023932 JSL $C2BB34 SR: $02BB34 戦闘中キャラクターIDから通常キャラクターIDへ変換
023936 STX $258B $258B=X
023939 JSR $3965 SR: $023965 コマンド入力の必要があるか(ないc=on)
02393C BCS #$F1 if(c==on) goto $02392F
02393E DEC $38B0 $38B0–
023941 LDA $38B0 A=$38B0
023944 JSL $C3B4F9 SR: $03B4F9 指定ページ以上の深さのバッファクリア
023948 BRA #$87 goto $0238D1
02394A PLA Pull A
02394B SEC c=on
02394C RTS return

基本的にはパーティ人数を取得し、コマンド入力の必要があるかどうかを判断し、必要がなければスキップするというループを人数分繰り返しています。$02392F-以降の処理は戦闘コマンド入力ウィンドウでキャンセルをおした時の処理です。1つ前に戻るわけですが、死人などコマンド入力のひつようのないキャラクターをスキップするということをやっています。Yが#$FFFFになったら一番先頭ということなので1つ前のウィンドウに戻ります。

  • SR:$02C197 AI行動決定の必要があるか(ないc=on)
02C197 PHP Push P Flag
02C198 REP #$30 m=off(A/M:16b) x=off(X/Y:16b)
02C19A PHA Push A
02C19B PHX Push X
02C19C PHY Push Y
02C19D PHB Push DB
02C19E PEA #$7E7E Push #$7E7E
02C1A1 PLB Pull DB
02C1A2 PLB Pull DB
02C1A3 LDX $258B X=$258B
02C1A6 JSL $C2EFA7 SR: $02EFA7 引数:1#$204E 引数:2#$0007 グループIDを収得
02C1AE CMP #$0006 A>=#$0006? PC側でなければスキップ
02C1B1 BCC #$30 if(c==off) goto $02C1E3
02C1B3 JSL $C2EFA7 SR: $02EFA7 引数:1#$204F 引数:2#$00FF キャラクターID取得
02C1BB JSL $C45D7A SR: $045D7A 引数:1#$FF 引数:2#$FF
02C1C1 CMP #$0002 A==#$0002?
02C1C4 BEQ #$1D if(z==on) goto $02C1E3
02C1C6 JSL $C2EFF4 SR: $02EFF4 引数:1#$2052 引数:2#$0004 ドラゴラム中ならスキップ
02C1CE BNE #$13 if(z==off) goto $02C1E3
02C1D0 JSL $C2EFF4 SR: $02EFF4 引数:1#$2053 引数:2#$0020 名前がもどき中ならスキップ
02C1D8 BNE #$09 if(z==off) goto $02C1E3
02C1DA PLB Pull DB
02C1DB REP #$30 m=off(A/M:16b) x=off(X/Y:16b)
02C1DD PLY Pull Y
02C1DE PLX Pull X
02C1DF PLA Pull A
02C1E0 PLP Pull P Flag
02C1E1 CLC c=off
02C1E2 RTL return
02C1E3 PLB Pull DB
02C1E4 REP #$30 m=off(A/M:16b) x=off(X/Y:16b)
02C1E6 PLY Pull Y
02C1E7 PLX Pull X
02C1E8 PLA Pull A
02C1E9 PLP Pull P Flag
02C1EA SEC c=on
02C1EB RTL return

このSRはAI行動決定の際にも使用されていて他でも何箇所かで使われています。よくわからないのは$02C1BB-C4あたりで、恐らく「PC情報の何か」を参照しているようですが、全てのキャラクターで値が2のキャラクターは存在しないので事実上意味ありません。

  • SR:$023965 コマンド入力の必要があるか(ないc=on)
023965 PHY Push Y
023966 JSL $C2C197 SR: $02C197 AI行動決定の必要があるか(ないc=on)
02396A BCS #$59 if(c==on) goto $0239C5
02396C JSL $C42C26 SR: $042C26 引数:1#$01 引数:2#$FD 引数:3#$FF
023973 CMP #$0001 A==#$0001? キャラクターIDが主人公ならステータス判断部分に強制ジャンプ
023976 BEQ #$0A if(z==on) goto $023982
023978 JSL $C43488 SR: $043488 引数:1#$FF 作戦取得
02397D CMP #$0005 A==#$0005? さくせんが「めいれいさせろ」以外ならコマンド入力の必要なし
023980 BNE #$3F if(z==off) goto $0239C1
023982 LDX $258B X=$258B
023985 JSL $C2E4DC SR: $02E4DC 引数:1#$18 戦闘中情報取得/変更 死んでいたらスキップ
02398A BCS #$39 if(c==on) goto $0239C5
02398C JSL $C2EFA7 SR: $02EFA7 引数:1#$2050 引数:2#$0008 麻痺中ならスキップ
023994 BNE #$2B if(z==off) goto $0239C1
023996 JSL $C2EFA7 SR: $02EFA7 引数:1#$2050 引数:2#$00E0 眠っていたらスキップ
02399E BNE #$21 if(z==off) goto $0239C1
0239A0 JSL $C2EFA7 SR: $02EFA7 引数:1#$2055 引数:2#$00C0 休み中ならスキップ
0239A8 BNE #$17 if(z==off) goto $0239C1
0239AA JSL $C2EFA7 SR: $02EFA7 引数:1#$2056 引数:2#$0080 精霊の歌を歌っている最中ならスキップ
0239B2 BNE #$0D if(z==off) goto $0239C1
0239B4 JSL $C2EFA7 SR: $02EFA7 引数:1#$205D 引数:2#$0080 パルプンテによる凍りつき中ならスキップ
0239BC BNE #$03 if(z==off) goto $0239C1
0239BE PLY Pull Y
0239BF CLC c=off
0239C0 RTS return
0239C1 JSL $C2C2F5 SR: $02C2F5 知能が神の場合の戦闘行動決定
0239C5 PLY Pull Y
0239C6 SEC c=on
0239C7 RTS return

この辺はお約束というか、行動不能フラグを1個ずつ見ていってどれかに該当していたらコマンド入力はなし、というだけです。この辺は基本的な部分なのでこれといっていじるような場所でもないので「そういうもの」という理解でいいと思います。

  • SR:$02C2F5 知能が神の場合の戦闘行動決定
02C2F5 PHP Push P Flag
02C2F6 REP #$30 m=off(A/M:16b) x=off(X/Y:16b)
02C2F8 PHA Push A
02C2F9 PHX Push X
02C2FA PHY Push Y
02C2FB PHB Push DB
02C2FC PEA #$7E7E Push #$7E7E
02C2FF PLB Pull DB
02C300 PLB Pull DB
02C301 LDX $258B X=$258B
02C304 JSL $C2C331 SR: $02C331 行動情報リセット
02C308 JSL $C2E7DB SR: $02E7DB 引数:1#$04 行動回数決定
02C30D TAY Y=A Yが0になるまでセットし続ける
02C30E LDA #$8198 A=#$8198 「行動直前に戦闘行動を決定」の戦闘行動・対象値
02C311 JSL $C2EF6B SR: $02EF6B 引数:1#$2034 戦闘中キャラクター情報変更 インデックス:X
02C317 DEY Y–
02C318 BEQ #$0F if(z==on) goto $02C329
02C31A JSL $C2EF6B SR: $02EF6B 引数:1#$2036 戦闘中キャラクター情報変更 インデックス:X
02C320 DEY Y–
02C321 BEQ #$06 if(z==on) goto $02C329
02C323 JSL $C2EF6B SR: $02EF6B 引数:1#$2038 戦闘中キャラクター情報変更 インデックス:X
02C329 PLB Pull DB
02C32A REP #$30 m=off(A/M:16b) x=off(X/Y:16b)
02C32C PLY Pull Y
02C32D PLX Pull X
02C32E PLA Pull A
02C32F PLP Pull P Flag
02C330 RTL return

「知能が神の場合の戦闘行動決定」の「神」というのは要は「行動直前に戦闘行動を決められる」キャラクターのことです。モンスター側は「人間」「バカ」があるのでこういう呼び名になっているようです。PC側のAIはすべて直前に行動を決めているので全員神扱いです。

  • SR:$02E8C6 PC側固定情報取得SR_SR_0002(行動回数決定)
02E8C6 JSL $C45DE4 SR: $045DE4 引数:1#$FD 引数:2#$FF AI時行動回数設定を取得
02E8CC CMP #$0000 A==#$0000? 1回
02E8CF BNE #$02 if(z==off) goto $02E8D3
02E8D1 INC A++
02E8D2 RTS return
02E8D3 DEC A–
02E8D4 BNE #$09 if(z==off) goto $02E8DF 1~2回
02E8D6 JSL $C00E97 SR: $000E97
02E8DA AND #$0001 A&=#$0001 50%の確率で2回行動
02E8DD INC A++
02E8DE RTS return
02E8DF DEC A– 2回行動
02E8E0 BNE #$03 if(z==off) goto $02E8E5
02E8E2 INC A++
02E8E3 INC A++
02E8E4 RTS return
02E8E5 INC A++ 3回行動は強すぎるのでボツ?
02E8E6 INC A++
02E8E7 RTS return

SR: $02E7DBは最終的にはこのSRを呼び出します。各キャラクターのAI行動時の行動回数情報を取得し、行動回数を決定します。行動回数1~2回のキャラ(キラーマシン2だけ)は50%の確率で2回行動をすることがわかります。2ビット使って3パターンしかないのでもう1パターン追加するのは比較的簡単そうです。いじるなら2回行動の確率を33%にするとか、66%にするとかでしょうか。そもそもAIのほうが有利な行動をするというのはどうかと思うんですが(誰もマニュアルを使わなくなるので)、DQ6では個別作戦指定ができないのと、戦闘中使用して効果のある道具を使ってくれないのであっという間にMPが枯渇するくらいがデメリットと言えなくもないのですが、もうちょっと何とかしたい部分ではあります。

コメント

  1. 匿名 より:

    レベルに依存して2回行動の確率があがっていくとか面白そうです

    管理者より返信:

    それもありでしょうね。オリジナルでは1~2回攻撃をするのはキラーマシン2しかいませんが、レベル上限の高い弱めの(笑)仲間に対しても適用すれば2回攻撃が発生する率がそっちの方が高い、という状況を作れていいかもしれません。

  2. 匿名 より:

    敵モンスターにもレベル設定されてるみたいなのでいろいろ強弱つけれそうですね

    管理者より返信:

    上記の部分はPC側の話なので、モンスター側の行動回数決定はまた別の箇所にあるはずです。まだ調べていませんが。恐らく1~2回行動は同じように1/2の確率で決めてると思います。レベルによる回数判定の変化をモンスター側にも導入するというのは、モンスター側、PC側を統一するという意味ではいいかもしれませんが、労力に見合う目に見える差が実感できるかが疑問です。